Random Two-mode Networks

tnet » Two-mode Networks » Random Networks

When analysing network and computing measures, it is difficult to gauge whether the outcome is “high” or “low”. For example, is a 0.3 clustering coefficient high or low? Random networks based on an observed network can be used as to create a benchmark value. In other words, an observed value (e.g., a clustering coefficient) can be compared to the distribution of clustering coefficient from corresponding random networks.

There are many procedures or null models for creating random networks in one-mode networks. These procedures vary in how much they randomise an observed network. Traditionally, classical (also known as Bernoulli or Erdos-Reyni) random networks were the commonly used. These networks are constructed by using the same number of nodes, and assigning each dyad a uniform probability of having a tie based on the number of observed ties. In these networks, the degree distribution is uniform or Poisson. However, such a distribution rarely exist in reality. In fact, most real-world distributions are skewed. In response to the lack of comparability between observed networks and classical random networks, a set of randomisation procedures that maintain additional features has been developed. First, by reshuffling ties in an observed network, it is possible to create random networks that maintain each node’s number of ties as well as the overall number of nodes and ties (Molloy and Reed, 1995). Second, for weighted networks, it is also possible to reshuffle only the weights. By maintaining the ties and simply reshuffling tie weights, features based on connectedness are maintained (e.g., the size of the largest interconnected group of nodes; Opsahl et al., 2008).

The procedures for creating random networks in one-mode networks can be ported to two-mode networks. This page describes the counterparts to classical random network, tie reshuffled, and weighted reshuffled networks.

Classical Random Two-mode Networks

Classical random networks are created by setting the number of nodes and giving all possible ties a uniform probability of being formed. This probability is often the density of networks (i.e., number of directed ties or 2x undirected ties over Nx(N-1)). This procedure can be ported to two-mode networks by setting the numbers of primary and secondary nodes and giving all possible ties (i.e., ties between nodes in different groups) a uniform probability of being formed. To create corresponding networks, this probability would be using the two-mode density metric instead of the one-mode one: number of ties divided by the product of the numbers of primary and secondary nodes. This procedure is implemented in the function rg_tm in tnet.

Link Reshuffling

As nodes’ degree are not uniformely distributed, a second procedure for creating random networks consists in reshuffling the topology, reaching the maximally random network with the same degree distribution as the observed network (Maslov and Sneppen, 2002; Newman, 2003). For two-mode networks, a similar procedure can be conducted that ensures that nodes maintain their number of connections. This null model is implemented in the rg_reshuffling_tm-function with the option parameter set to “links”.

Weight Reshuffling

While the link reshuffling procedure can be applied to binary networks, another procedures is possible to use when dealing with weighted two-mode networks. The weight reshuffling procedure consists simply in reshuffling the weights globally in the network (Opsahl et al., 2008). This null model maintains the topology of the observed network. Therefore, the number of ties originating from a node (degree) does not change. Moreover, other features, such as the giant component does not change as well. This null model is also implemented in the rg_reshuffling_tm-function with the option parameter set to “weights”.

Want to test it with your data?

The randomisation procedures are implemented in tnet. First, you need to download and install tnet in R. Then, you need to create an edgelist of your network (see data structures in tnet for weighted two-mode networks). The commands below show how corresponding random networks to the Davis’ Southern Women data (Davis et al., 1941) can be created.

# Load tnet and Davis’ Southern Women network
net <- Davis.Southern.women.2mode

# Bernoulli / Erdos Renyi (find the number of nodes and density first)
n1 <- length(unique(net[,1]))
n2 <- length(unique(net[,2]))
ptie <- nrow(net)/(n1*n2)
rg_tm(ni=n1, np=n2,ties=ptie)

# Tie reshuffling
rg_reshuffling_tm(net, option="links")

# Weight reshuffling (add random weights first)
netw <- cbind(net, sample(1:4, size=nrow(net),  replace=TRUE))
rg_reshuffling_tm(netw, option="weights")


Davis, A., Gardner, B. B., Gardner, M. R., 1941. Deep South. University of Chicago Press, Chicago, IL.

Molloy, M., Reed, B., 1995. A critical point for random graphs with a given degree sequence. Random Structures and Algorithms 6, 161-180.

Opsahl, T., Colizza, V., Panzarasa, P., Ramasco, J. J., 2008. Prominence and control: The weighted rich-club effect. Physical Review Letters 101 (168702). arXiv:0804.0417.

Opsahl, T., 2013. Triadic closure in two-mode networks: Redefining the global and local clustering coefficients. Social Networks 35, doi:10.1016/j.socnet.2011.07.001.

If you use any of the information on this page, please cite: Opsahl, T., 2013. Triadic closure in two-mode networks: Redefining the global and local clustering coefficients. Social Networks 35, doi:10.1016/j.socnet.2011.07.001

8 Comments Add your own

  • 1. Thomas  |  August 30, 2013 at 10:18 am

    Hello Tore,

    I am using the rg_tm function to create a random network. I would like to know if there is a difference in the resulting degree distribution of the network if (1) I put in the exact number of ties (e.g. ties=300) or (2) if I Put in the probability of having a tie (e.g. ties=0.05).
    For example that the degree in the second case is a Poisson distribution while in the first case there is no distribution function but just a single value.

    Best regards,

    • 2. Tore Opsahl  |  September 3, 2013 at 1:41 am

      Hi Thomas,

      The difference is the method used for creating the network. When you set the probability, each tie has this probability of being created — i.e., whether or not each individual tie exists is completely independent of the other ties. In the resulting network, there approximately -but not exactly be- (probability*n*(n-1)) ties. Conversely, if the number of ties is specified (e.g., ties=300), there will be exactly that amount of ties in the resulting network. In this case, the ties are not completely independent of each other as the number is fixed.

      In terms of the degree distribution, both methods will create a classical random network with a Poisson distribution. If you would like to maintain a degree distribution, see the rg_reshuffling_tm-function.


  • 3. Matthew E Parker  |  February 16, 2017 at 6:42 pm

    I am extremely new to R and tnet, so please bear with me. I have several 2-mode networks and I am trying to compare their reinforcement and clustering measures with that of a random network. For one network I have come up with the following code to create a comparable random network:

    randonet <- rg_tm(ni=1125,np=338,ties=1504,weights=1,seed=NULL)
    randonet <- as.tnet(randonet, type="binary two-mode tnet")

    As far as I can tell, this has worked fine. However, I would like to stabilize the random measurements by averaging the values from multiple random networks. Is there an easy way to do the above procedure to, for example, 1,000 random networks simultaneously and then output the averages of the resulting measures?

    • 4. Tore Opsahl  |  February 22, 2017 at 2:02 am

      Hi Matthew,

      The easiest way to do this is to create an output vector and then a loop. Below is an example snippet of code.


      # Load tnet
      # Initialize output vector
      out <- rep(NaN, 1000)
      # Loop across
      for(i in 1:length(out)) {
        # Generate random network
        randonet <- rg_tm(ni=1125,np=338,ties=1504,weights=1,seed=i)
        # Compute reinforcement and store in output vector
        out[i] <- reinforcement_tm(randonet)
      # Average score
  • 5. Elena Stasewitsch  |  May 2, 2017 at 1:00 pm

    Hi Tore,
    I have a two-mode, undirected, unweighted network. One mode are people, the other are projects that they participated in. I calculated (with all the code from your website! Thanks!) betweenness and so on. Now I want to create 1000 random networks and see if my estimates are significantly different from the random networks. Therefore I need to write a loop. I am not quite sure whether my code makes any sense. Can you take a look? There is no Error or something, but the output is quite confusing. I want to transfer the random network data into SPSS and calculate mean betweenness for example and than do some t-tests (or something else) in order to see if there is a significant difference. Have you done something like this already?
    And if I print(tmp) the output is a list. But it should be 1000 different lists with the betweenness of each random network. Or am I mistaken?
    Thank you for your help:)

    out4 <- rep(twomode5, 1000)
    # Loop across

    for(i in 1:length(out4)) {

    # Generate random network
    n1 <- length(unique(twomode5[,1]))
    n2 <- length(unique(twomode5[,2]))
    ptie <- nrow(twomode5)/(n1*n2)
    randonet andere Messung closure (brauch ich nt)
    out5<- reinforcement_tm(randonet)

    # Compute betweenness
    net <- projecting_tm(randonet, "Newman")
    tmp <- betweenness_w(net )[,"betweenness"]

    print (tmp)

    Best regards,

  • 6. Elena Stasewitsch  |  May 2, 2017 at 2:10 pm

    Hi Tore,
    me again. I tried doing this:

    out4 <- c(1,2,3,4,5,6,7,8,9,10)

    # Loop across
    for(i in 1:length(out4)) {

    # Generate random network
    randonet4 andere Messung closure (brauch ich nt)
    out4[i]<- reinforcement_tm(randonet4) }


    And it helps I get different reinforcement values. But if I try this loop with something" as complex" as this:

    out5 <- c(1,2,3,4,5,6,7,8,9,10)
    # Loop across
    for(i in 1:length(out5)) {

    # Generate random network
    randonet5 <- rg_tm(ni=133,np=48,ties=190,weights=1,seed=i)

    # Compute
    out5[i] <- projecting_tm(randonet5, "Newman")

    out6 <- betweenness_w(out5[i])[,"betweenness"]}

    print (out6)

    I get this warning message:

    Error in if (NC == 2) net <- data.frame(tmp[, 1], tmp[, 2]) :
    argument is of length zero
    In out5[i] <- projecting_tm(randonet5, "Newman") :
    number of items to replace is not a multiple of replacement length

    Can you help?


    • 7. Tore Opsahl  |  May 4, 2017 at 7:12 pm

      Hi Elena,

      Please read up on the various data types in R. When you create a vector of numbers from 1 to 10, you can only replace each of these values with another value and not an object. If you would like to store objects within objects, use lists.


      • 8. Elena Stasewitsch  |  May 5, 2017 at 6:55 am

        Hi Tore,
        thank you, will do that:)!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed

%d bloggers like this: