Longitudinal Data Structure

tnet » Software » Longitudinal Data Structure

Networks evolve.

Networks evolve as a result of the joining and leaving of nodes, and the creating, reinforcing, weakening, and severing of ties. For example, one network that is currently receiving a great deal of attention in the literature is the network of commercial airports (the nodes) that are tied together by scheduled flights. This network grows when new airports open and shrinks when old ones close down. Ties are created when new routes are started and reinforced if the capacity of an existing route is increased. Weakening of a tie occurs when airlines cut capacity, which ultimately results in the severing of the tie if all airlines terminate flights on the route. Yet, the evolution of networks is typically not recorded. This implies that the dependency structure among ties is unknown.

Longitudinal networks should be represented by a four-column edgelist to be analysed in tnet. The columns correspond to (1) the timing using a character string the following format surrounded by quotes: “YYYY-MM-DD HH:MM:SS”, (2) the sender or originator of the tie, (3) the receiver or target node of the tie, and (4) the tie weight. Note that the tie weight-column is not the cumulative tie weight, but the change in tie weight. As such, a negative value signal a weakening of the tie.

Node joining and leaving data is directly incorporated in the edgelist by the inclusion of a self-loop (i.e., a tie from a node to itself). The tie weight of the self-loops differentiates node joining (weight=1) and leaving (weight=-1). If the data do not contain node joining information, the as.tnet-function will include nodes right before the creation of the tie. See the code below.

The network in the animated diagram above should be represented as follows in R (note that the first column is a character string, while the others are integer or numeric).

                     [,1] [,2] [,3] [,4]
 [1,] 2007-09-12 13:45:00    1    1    1
 [2,] 2007-09-12 13:45:00    2    2    1
 [3,] 2007-09-12 13:45:00    1    2    1
 [4,] 2007-09-12 13:46:31    1    2    1
 [5,] 2007-09-12 13:47:54    1    2    1
 [6,] 2007-09-12 13:48:21    1    2    1
 [7,] 2007-09-12 13:49:27    1    2    1
 [8,] 2007-09-12 13:51:14    1    2   -1
 [9,] 2007-09-12 13:52:17    3    3    1
[10,] 2007-09-12 13:52:17    1    3    1
[11,] 2007-09-12 13:56:59    1    3    1

Loading Your Network

The most common way of loading a network is to read a text file with the network. The read.table-function is the standard method for reading text files. This function works by giving it a filename or link, and a character for separating the values into columns (e.g., a tab). It is important to not just read, but also assign the read file to an object. To illustrate this procedure, the above network can be loaded into the object net using these commands (note that this file is on the web, and hence, the link instead of a filename).

# Read the network
net <- read.table("http://opsahl.co.uk/tnet/datasets/longitudinal-network.txt", sep="\t")

Ensure that the network conforms to the tnet standard

To ensure that the network conforms to the tnet standard, the as.tnet-function can be used. This function is run automatically by the functions if it has not been run on the network manually. This function takes two parameters: the network and a character string specifying the type of network. If the type parameter is not set, an object will be assumed to be a longitudinal edgelist if it has four columns. Below is the code for testing the network above.

# Load tnet

# Read the network
net <- read.table("http://opsahl.co.uk/tnet/datasets/longitudinal-network.txt", sep="\t")

# Check that it confirms to the tnet standard for weighted one-mode networks
net <- as.tnet(net, type="longitudinal tnet")
If you use tnet, please cite: Opsahl, T., 2009. Structure and Evolution of Weighted Networks. University of London (Queen Mary College), London, UK, pp. 104-122. Available at https://toreopsahl.com/publications/thesis/.

13 Comments Add your own

  • 1. joon  |  September 27, 2011 at 1:42 am

    great job !!!. But, when are you going to update this section?
    How,s your R longitudinal network project going? Any plan for sharing algorithms or libraries?

    • 2. Tore Opsahl  |  September 28, 2011 at 5:26 pm

      Thanks Joon,

      There should be an update to tnet 3.1 soon with new longitudinal functions. Have a look at the arXiv paper for the algorithms!


  • 3. Krishna  |  July 13, 2012 at 6:30 pm

    Is tnet package version 3.1 updated yet? I am looking for algorithms to do some analysis on longitudinal network. Will you be able to suggest me any package/s?

    • 4. Tore Opsahl  |  July 13, 2012 at 6:44 pm


      Version 3.0.7 was just put up this week. I am trying to incorporate a new growth_l-function for version 3.1. What other longitudinal functions are you looking for?


  • 5. Krishna  |  July 13, 2012 at 8:18 pm

    Thanks, I am specifically looking for Network evolution and random longitudinal network functions.

  • 6. Seemanta  |  November 23, 2012 at 5:04 am

    Hi Tore,

    I have a longitudinal data named ‘sample’ as shown below:
    t i j w
    1 2012-08-24 13:14:00 1 1 1
    2 2012-08-24 13:14:00 1 1 1
    3 2012-10-15 15:06:00 16 16 1
    4 2012-09-29 11:45:00 139 139 1
    5 2012-09-13 10:31:00 262 262 1
    6 2012-09-21 12:33:00 385 385 1
    7 2012-10-29 18:04:00 508 458 1
    8 2012-10-29 18:04:00 508 458 1
    9 2012-09-04 02:20:00 631 470 1
    10 2012-09-13 09:33:00 687 482 1
    11 2012-09-27 03:13:00 699 494 1
    12 2012-08-31 06:41:00 687 112 1

    where t is character and i,j,w are numeric
    But I am getting the following error when I execute

    > as.tnet(sample)

    Error in as.tnet(sample) : Problem with node joining data

    Any suggestions?


    • 7. Tore Opsahl  |  November 23, 2012 at 10:52 pm

      Hi Seemanta,

      It seems that the network has multiple node joining data points. Node joining is signaled by self-loops (i.e., the node id of the joining node in both the i and j columns) and a 1 in the w column (e.g., like row 1, 2, 3, 4, 5, and 6 in your network). If the dataset does not have any node joining rows, then node joining rows are added automatically. However, if at least one node joining is present, a check is done to ensure that all nodes in the network has joining information.

      Your network does not pass this check as a node cannot join twice (e.g., node 1 joins the network in rows 1 and 2), and not all nodes have joining information (e.g., in row 7, a tie is formed from 508 to 458 but neither of these nodes have joined the network).

      Hope this helps,

      • 8. Seemanta  |  November 24, 2012 at 6:46 am

        Got it..thanks a lot…

  • 9. Sam  |  May 22, 2016 at 9:21 pm

    I keep receiving the “network not loaded properly” message even when I’m running an Rscript you’ve provided:
    net2 <- cbind(
    # Calculate measures
    closeness_w(net, gconly=FALSE)
    Error in closeness_w(net, gconly = FALSE) : Network not loaded properly.

    I downloaded the package from CRAN, so I'm assuming I don't have an outdated version. What is this message typically referring to?

    Thank you for any feedback,

    • 10. Tore Opsahl  |  May 24, 2016 at 12:59 am

      Hi Sam,

      That piece of code seems to work well if you change the network object from net2 to be net.


  • 11. jrdorning  |  June 7, 2016 at 12:09 pm

    I think I’ve found a bug in tnet: it doesn’t calculate a closeness score for the last individual in a matrix (the last row and column) if the column contains all zeros (so the animal did not associate with any other animal during the sampling period).

    • 12. jrdorning  |  June 7, 2016 at 12:13 pm

      Sorry I seem to have posted this on the wrong page – I meant to post it on the closeness page but I have too many tabs open and got confused.

      Another question – I have a few matrices that involve only 4 individuals and tnet is trying to treat them as longitudinal networks rather than association matrices. I tried specifying “weighted one-mode network” but get the error “Type of network not recognised”. Any help to get around this issue would be very much appreciated!

    • 13. Tore Opsahl  |  June 14, 2016 at 5:39 pm


      This is an issue with the edgelist representation used internally in tnet. Have a look at this post for a work-around: https://toreopsahl.com/2010/03/20/closeness-centrality-in-networks-with-disconnected-components/

      Also, please see the help file by typing ?as.tnet:

      net: A network in an edgelist or matrix format. It can be a weighted one-mode network, a binary two-mode network, a weighted two-mode network, or a longitudinal network. If the data-object has two-columns, it is assumed to be a binary two-mode network; three columns, weighted one-mode network; four columns, longitudinal; five or more and the same number of rows and columns, weighted one-mode network; five or more and –not– the same number of rows and columns, it is assumed to be a two-mode network.

      type: If you would like to specify the type of network. This could be “weighted one-mode tnet”, “binary two-mode tnet”, “weighted two-mode tnet”, or “longitudinal tnet”.

      You should specify “weighted one-mode tnet”. As a general rule, the edgelist format is better as then the network is not transformed.



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 )

Twitter picture

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

Facebook photo

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

Connecting to %s

Subscribe to the comments via RSS Feed

%d bloggers like this: