These functions are similar to the create_* functions, but include some element of randomisation. They are particularly useful for creating a distribution of networks for exploring or testing network properties. The networks here start from a planted structure, to which some random noise is then added.

  • generate_smallworld() generates a small-world structure via ring rewiring at some probability.

  • generate_islands() generates an islands model.

  • generate_communities() generates communities of unequal size among nodes of unequal degree.

  • generate_core() generates a core and a periphery, as the random counterpart of create_core().

generate_islands() and generate_communities() plant discrete groups, and record the group of each node in the node attribute community. generate_core() plants two, and records whether each node is in the core in the node attribute core. generate_smallworld() plants local clusters around a ring instead, so its nodes do not belong to discrete groups.

These functions can create either one-mode or two-mode networks. To create a one-mode network, pass the main argument n a single integer, indicating the number of nodes in the network. To create a two-mode network, pass n a vector of two integers, where the first integer indicates the number of nodes in the first mode, and the second integer indicates the number of nodes in the second mode. As an alternative, an existing network can be provided to n and the number of modes, nodes, and directedness will be inferred.

generate_smallworld(n, p = 0.05, directed = FALSE, width = 2)

generate_islands(n, p = 0.5, directed = FALSE, width = 1, groups = 2, ...)

generate_communities(
  n,
  p = 0.1,
  directed = FALSE,
  groups = NULL,
  degree = NULL,
  max_degree = NULL,
  degree_exp = 2,
  community_exp = 1
)

generate_core(n, p = 0.5, directed = FALSE, mark = NULL)

Arguments

n

Given:

  • A single integer, e.g. n = 10, a one-mode network will be created.

  • A vector of two integers, e.g. n = c(5,10), a two-mode network will be created.

  • A manynet-compatible object, a network of the same dimensions will be created.

p

The main probability of the model, which is what makes a network of it more or less random. It always follows n, and what it is the probability of depends on the model. For generate_smallworld(), it is the probability that each tie of the ring is rewired, by default 0.05. For generate_islands(), it is the probability of a tie between two nodes of the same island, by default 0.5. For generate_communities(), it is the probability that a tie of a node leads out of its community, known as the mixing parameter, by default 0.1: a low value gives communities that are easy to tell apart, and a value above 0.5 gives communities with more ties out than in. For generate_core(), it is the probability of a tie between a node of the core and a node of the periphery, by default 0.5, or a vector of three: the probabilities of a tie within the core, between the two, and within the periphery.

directed

Logical whether the network should be directed. By default directed = FALSE, but for the functions that the usage above shows another default for. A network given as n sets the direction instead. If the opposite direction is desired, use to_redirected() on the output of these functions. In two-mode networks, the directed argument is ignored.

width

Integer specifying the width of the ring, breadth of the branches, number of nodes in each blade of a windmill, maximum extent of the neighbourbood, or number of ties that bridge each pair of islands.

groups

How the nodes are divided into groups, in one of three ways:

  • A single integer, e.g. groups = 3, is the number of groups, which are then as equal in size as they can be.

  • A vector of integers that sum to the number of nodes, e.g. groups = c(10, 20, 30) for 60 nodes, is the size of each group.

  • Any other two integers, e.g. groups = c(10, 30), are the smallest and the largest that a group can be, and the sizes of the groups are drawn at random from between them.

Two integers that sum to the number of nodes are read as two sizes, and not as the smallest and the largest. In a two-mode network, a group has nodes of both modes, in the proportion of the two modes in the network as a whole, and its size is the size of the two together. The group of each node is recorded in the node attribute community. For generate_islands(), by default 2, and sizes between a smallest and a largest are all as likely as one another. For generate_communities(), by default the smallest and the largest are degree + 1 and max_degree + 1, so that a node of any degree can find all the ties it keeps within its community, and sizes between them are drawn from a power law.

...

Arguments under the names they had in earlier versions, which still work: islands for groups and bridges for width in generate_islands().

degree

The number of ties that a node sends. For generate_communities(), this is the mean over the nodes, by default 10, or less in a network too small for that. In a directed network, it is the mean number of ties that a node sends, which is also the mean number that a node receives. In a two-mode network, it is the mean degree of the nodes of the first mode, and the mean degree of the second mode follows from it, since both modes have the same ties: it is degree * n[1] / n[2].

max_degree

The maximum degree of the nodes. By default three times degree, or n - 1 if that is smaller. In a two-mode network, this can be one number for each mode, and is by default three times the mean degree of the mode, or the number of nodes in the other mode if that is smaller.

degree_exp

The exponent of the power law from which the degrees are drawn. By default 2. In a two-mode or directed network, this can be one number for each mode, or for the ties sent and the ties received.

community_exp

The exponent of the power law from which the community sizes are drawn. By default 1.

mark

A logical vector the length of the nodes in the network. This can be created by, among other things, any node_is_*() function.

Value

A stocnet object is returned, which can be coerced into other types of objects using as_edgelist(), as_matrix(), as_tidygraph(), as_igraph(), or as_network(). create_ring(), create_lattice(), generate_random(), generate_smallworld(), and generate_scalefree() return a tbl_graph or igraph object for now, since the released versions of the packages built on this one expect one from them.

By default, most networks are created as undirected. This can be overruled with the argument directed = TRUE. This will return a directed network in which the arcs are out-facing or equivalent. This direction can be swapped using to_redirected(). In two-mode networks, the directed argument is ignored.

Details

In generate_islands(), the nodes of an island are tied to one another with probability p, and width further ties bridge each pair of islands. In a two-mode network, a node of each mode that share an island are tied with probability p. Where a network is given as n, p is instead inferred from it, so that as many ties are expected as that network has.

generate_communities() follows the benchmark of Lancichinetti, Fortunato, and Radicchi (2008). Degrees and community sizes are each drawn from a power law, so that there are a few large hubs and a few large communities, as in many observed networks. Each node then keeps a share 1 - p of its ties within its community and sends the remaining share to nodes in other communities. Ties within and between communities are drawn at random from all the simple networks with those degrees. Where a degree sequence cannot be realised as a simple network, or a node has more ties to keep than its community has other members, ties are dropped or sent elsewhere, so the realised degrees and mixing can differ a little from those asked for. They differ most in small networks and where there are few communities.

The benchmark is defined for one-mode networks. For a two-mode network, generate_communities() extends it by analogy, in the same way that generate_islands() does for islands. Each community has nodes of both modes, in the proportion of the two modes in the network as a whole, and each mode draws its degrees from a power law of its own. A node then keeps a share 1 - p of its ties for the nodes of the other mode in its community. The two modes must keep the same number of ties in each community, and the ties that one mode has too many of there are dropped, so the realised degrees are a little lower than those asked for where p is low.

A directed network is treated in the same way, with the ties that a node sends and the ties that it receives in place of the two modes. Each node draws both from a power law, and keeps a share 1 - p of each within its one community. Lancichinetti and Fortunato (2009) define a directed benchmark too, from which this differs in how the two are drawn and reconciled, so it should not be taken for theirs.

generate_islands() is a simpler model of the same kind: the ties in each island are random, rather than following from degrees that differ, and each pair of islands is joined by a fixed number of bridges, rather than by a share of each node's ties.

In generate_core(), with a single p every pair of nodes in the core is tied and no pair in the periphery is, as in create_core(), and what is random is which nodes of the periphery each node of the core is tied to. With three, the core can be less than complete and the periphery less than empty, as Borgatti and Everett (2000) describe of observed networks. mark says which nodes are in the core, with TRUE for a node of the core, and by default they are the first half of the nodes, or of each mode. Note that create_core() for now reads a logical mark the other way round, with TRUE for a node of the periphery.

References

On small-world networks

Watts, Duncan J., and Steven H. Strogatz. 1998. “Collective Dynamics of ‘Small-World’ Networks.” Nature 393(6684):440–42. doi:10.1038/30918 .

On communities

Lancichinetti, Andrea, Santo Fortunato, and Filippo Radicchi. 2008. “Benchmark Graphs for Testing Community Detection Algorithms.” Physical Review E 78(4):046110. doi:10.1103/PhysRevE.78.046110

Lancichinetti, Andrea, and Santo Fortunato. 2009. “Benchmarks for Testing Community Detection Algorithms on Directed and Weighted Graphs with Overlapping Communities.” Physical Review E 80(1):016118. doi:10.1103/PhysRevE.80.016118

On cores and peripheries

Borgatti, Stephen P., and Martin G. Everett. 2000. “Models of Core/Periphery Structures.” Social Networks 21(4):375–95. doi:10.1016/S0378-8733(99)00019-2

Examples

generate_smallworld(12, 0.025)
#> IGRAPH 563d0be U--- 12 24 -- Watts-Strogatz random graph
#> + attr: name (g/c), dim (g/n), size (g/n), nei (g/n), p (g/n), loops
#> | (g/l), multiple (g/l)
#> + edges from 563d0be:
#>  [1]  1-- 2  2-- 3  3-- 4  4-- 5  5-- 6  6-- 7  7-- 8  8-- 9  9--10 10--11
#> [11] 11--12  1--12  1-- 3  1--11  2--12  2-- 4  3-- 5  4-- 6  5-- 7  6-- 8
#> [21]  7-- 9  8--10  9--11 10--12
generate_smallworld(12, 0.25)
#> IGRAPH 5ec7267 U--- 12 24 -- Watts-Strogatz random graph
#> + attr: name (g/c), dim (g/n), size (g/n), nei (g/n), p (g/n), loops
#> | (g/l), multiple (g/l)
#> + edges from 5ec7267:
#>  [1]  7-- 9  2-- 3  3-- 4  4-- 5  7--11  6-- 7  7-- 8  8-- 9  9--10  6--12
#> [11] 11--12  1--12  3-- 6  1--11  2--12  4-- 8  3-- 5  4-- 6  5-- 7  5-- 8
#> [21]  3-- 7  8--10  9--11  5--10
generate_islands(10)
#> 
#> ── # Islands network ───────────────────────────────────────────────────────────
#> # A undirected network of 10 nodes and 12 ties
#> 
#> ── Nodes 
#> # A tibble: 10 × 1
#>   community
#>       <int>
#> 1         1
#> 2         1
#> 3         1
#> 4         1
#> 5         1
#> 6         2
#> # ℹ 4 more rows
#> 
#> ── Ties 
#> # A tibble: 12 × 2
#>    from    to
#>   <int> <int>
#> 1     1     3
#> 2     1     4
#> 3     2     4
#> 4     1     5
#> 5     4     5
#> 6     6     8
#> # ℹ 6 more rows
#> 
generate_islands(12, groups = c(3, 4, 5), width = 2)
#> ── # Islands network ───────────────────────────────────────────────────────────
#> # A undirected network of 12 nodes and 14 ties
#> 
#> ── Nodes 
#> # A tibble: 12 × 1
#>   community
#>       <int>
#> 1         1
#> 2         1
#> 3         1
#> 4         2
#> 5         2
#> 6         2
#> # ℹ 6 more rows
#> 
#> ── Ties 
#> # A tibble: 14 × 2
#>    from    to
#>   <int> <int>
#> 1     1     3
#> 2     4     6
#> 3     8     9
#> 4     8    10
#> 5     9    10
#> 6     8    11
#> # ℹ 8 more rows
#> 
generate_islands(c(10, 6))
#> ── # Islands network ───────────────────────────────────────────────────────────
#> # A two-mode network of 10 FALSEs and 6 TRUEs and 14 ties
#> 
#> ── Nodes 
#> # A tibble: 16 × 2
#>   mode  community
#>   <chr>     <int>
#> 1 FALSE         1
#> 2 FALSE         1
#> 3 FALSE         1
#> 4 FALSE         1
#> 5 FALSE         1
#> 6 FALSE         2
#> # ℹ 10 more rows
#> 
#> ── Ties 
#> # A tibble: 14 × 2
#>    from    to
#>   <int> <int>
#> 1     1    13
#> 2     2    11
#> 3     2    12
#> 4     3    11
#> 5     3    13
#> 6     4    16
#> # ℹ 8 more rows
#> 
generate_communities(50)
#> ── # Communities network ───────────────────────────────────────────────────────
#> # A undirected network of 50 nodes and 251 ties
#> 
#> ── Nodes 
#> # A tibble: 50 × 1
#>   community
#>       <int>
#> 1         1
#> 2         1
#> 3         1
#> 4         1
#> 5         1
#> 6         1
#> # ℹ 44 more rows
#> 
#> ── Ties 
#> # A tibble: 251 × 2
#>    from    to
#>   <int> <int>
#> 1     1     5
#> 2     1    11
#> 3     1    13
#> 4     1    15
#> 5     1    18
#> 6     1    21
#> # ℹ 245 more rows
#> 
generate_communities(50, p = 0.4)
#> ── # Communities network ───────────────────────────────────────────────────────
#> # A undirected network of 50 nodes and 228 ties
#> 
#> ── Nodes 
#> # A tibble: 50 × 1
#>   community
#>       <int>
#> 1         1
#> 2         1
#> 3         1
#> 4         1
#> 5         1
#> 6         1
#> # ℹ 44 more rows
#> 
#> ── Ties 
#> # A tibble: 228 × 2
#>    from    to
#>   <int> <int>
#> 1     1    10
#> 2     1    11
#> 3     1    21
#> 4     1    29
#> 5     1    50
#> 6     2     4
#> # ℹ 222 more rows
#> 
generate_communities(50, directed = TRUE, groups = 3)
#> ── # Communities network ───────────────────────────────────────────────────────
#> # A directed network of 50 nodes and 484 arcs
#> 
#> ── Nodes 
#> # A tibble: 50 × 1
#>   community
#>       <int>
#> 1         1
#> 2         1
#> 3         1
#> 4         1
#> 5         1
#> 6         1
#> # ℹ 44 more rows
#> 
#> ── Ties 
#> # A tibble: 484 × 2
#>    from    to
#>   <int> <int>
#> 1     1     2
#> 2     1     5
#> 3     1     6
#> 4     1    10
#> 5     1    11
#> 6     1    12
#> # ℹ 478 more rows
#> 
generate_communities(c(60, 40))
#> ── # Communities network ───────────────────────────────────────────────────────
#> # A two-mode network of 60 FALSEs and 40 TRUEs and 543 ties
#> 
#> ── Nodes 
#> # A tibble: 100 × 2
#>   mode  community
#>   <chr>     <int>
#> 1 FALSE         1
#> 2 FALSE         1
#> 3 FALSE         1
#> 4 FALSE         1
#> 5 FALSE         1
#> 6 FALSE         1
#> # ℹ 94 more rows
#> 
#> ── Ties 
#> # A tibble: 543 × 2
#>    from    to
#>   <int> <int>
#> 1     1    63
#> 2     1    67
#> 3     1    68
#> 4     1    78
#> 5     1    79
#> 6     1    80
#> # ℹ 537 more rows
#> 
generate_core(12)
#> ── # Core-periphery network ────────────────────────────────────────────────────
#> # A undirected network of 12 nodes and 35 ties
#> 
#> ── Nodes 
#> # A tibble: 12 × 1
#>   core 
#>   <lgl>
#> 1 TRUE 
#> 2 TRUE 
#> 3 TRUE 
#> 4 TRUE 
#> 5 TRUE 
#> 6 TRUE 
#> # ℹ 6 more rows
#> 
#> ── Ties 
#> # A tibble: 35 × 2
#>    from    to
#>   <int> <int>
#> 1     1     2
#> 2     1     3
#> 3     1     4
#> 4     1     5
#> 5     1     6
#> 6     1     9
#> # ℹ 29 more rows
#> 
generate_core(12, p = c(0.8, 0.3, 0.1))
#> ── # Core-periphery network ────────────────────────────────────────────────────
#> # A undirected network of 12 nodes and 23 ties
#> 
#> ── Nodes 
#> # A tibble: 12 × 1
#>   core 
#>   <lgl>
#> 1 TRUE 
#> 2 TRUE 
#> 3 TRUE 
#> 4 TRUE 
#> 5 TRUE 
#> 6 TRUE 
#> # ℹ 6 more rows
#> 
#> ── Ties 
#> # A tibble: 23 × 2
#>    from    to
#>   <int> <int>
#> 1     1     3
#> 2     1     4
#> 3     1     9
#> 4     1    10
#> 5     2     3
#> 6     2     5
#> # ℹ 17 more rows
#>