Introduction

The netTS package is meant for relational data taking place through time. The point of this package is to facilitate the analyses of time-aggregated social networks using a moving window approach.

This approach allows a user to define the size of a time window (e.g., windowsize = 1 month) and the amount to move the window (e.g., windowshift = 1 day). This moving window then subsets the relational data within a window, creates a network and extracts a network measure. It then shifts over in time and repeats the process. By altering the size and shift of this moving window it is then possible to measure how networks change in time.

The main functions in the package are:

  1. graphTS - Extract network level measures (e.g., mean strength)
  2. nodeTS - Extract node level measures (e.g., node in-strength)
  3. dyadTS - Extract dyad level measures (e.g., dyad weight)
  4. check.windowsize - Estimate the uncertainty of a network measure at a chosen window size
  5. check.timescale - Estimate how a network measure changes as window size changes

Look at some example data

First install netTS and load some useful libraries

#if netTS is not yet installed you can use the following code to install it from github:
#devtools::install_github("tbonne/netTS")

library(netTS)
library(lubridate)
library(ggplot2)
library(igraph)
library(reshape2)

Here we make use of some vervet monkey grooming data (a highly gregarious primate). This data is in the rquired format for working with netTS. The first two coloumns should have information about what two individuals/entities are interacting. The third column should contain dates/times. This last column should be in date format (e.g., ymd, or ymd_hms). The lubridate package can be helpful for setting this up. Finaly, it is possible to record weights, sampling information, or any other useful information as additional columns.

#1. Take a look at the raw data
head(groomEvents)
##     ID PartnerID                date
## 1 Laur      Malc 2015-07-01 12:32:19
## 2 Malc      Laur 2015-07-01 12:33:01
## 3 Ubun      Wall 2015-07-01 16:08:26
## 4 Wall      Ubun 2015-07-01 16:09:52
## 5 Dott      Jasm 2015-07-02 09:59:27
## 6 Jasm      Dott 2015-07-02 10:01:58

Extract graph level measures through time.

The graphTS function requires windowsize and windowshift inputs to be in units of time. Again lubridate can be very useful here, as you can specify many kinds of times: e.g., years(10), months(10), hours(10), minutes(10), seconds(10). Additionally, a choice needs to be made for which network measure should be estimated through time. Here a measurement function needs to be created.

The idea of using functions is to provide flexibility and allow a wide range of network measures to be used. An example is provided below where: 1) a function is created, and 2) it is used to extract values from the data through time. The function below takes as an input a network and returns a single value - the mean out-degree of the network.

#1. create a small function
my.function.net <- function(graph){
  
  #calculate some measure from the graph
  my.value <- mean(degree(graph, mode="out"))
  
  #return the value 
  return(my.value)
  
}

#2. extract values through time
graph.values <- graphTS(groomEvents, windowsize = days(60), windowshift = days(10), measureFun = my.function.net, directed=TRUE)
## [1] "45 networks extracted"
#3. Take a look at the outputs
head(graph.values)
##     measure nEvents windowstart  windowend
## 2  9.033333     503  2015-07-01 2015-08-30
## 3  9.066667     464  2015-07-11 2015-09-09
## 4 10.400000     542  2015-07-21 2015-09-19
## 5 11.620690     612  2015-07-31 2015-09-29
## 6 11.517241     582  2015-08-10 2015-10-09
## 7 10.758621     523  2015-08-20 2015-10-19

Plot the graph level measures through time

#1. Plot the results
graphTS.plot(graph.values)

Extract node level measures through time.

It is also possible to ask how the network changes through time at the node level (i.e., the ego network). Here we look at how nodes change in out-degree through time. The measureFun for node level analysis should be a function that takes one network and returns a value for each node. An example is provided below.

#1. create a small function
my.function.nodes <- function(graph){
  
  #calculate some measure from the graph
  my.value <- degree(graph, mode="out")
  
  #return the values 
  return(my.value)
  
}

#2. extract values through time
node.values <- nodeTS(groomEvents, windowsize = days(60), windowshift = days(10), measureFun = my.function.nodes, directed=TRUE)
## [1] "45 networks extracted"
#3. Take a look at the output
head(node.values)
##   Laur Malc Ubun Wall Dott Jasm Meg Gunt Tear Zool Glit Xavi Razo Kels
## 2   13   12   10    8   13   11  11    8    9    8    2    7   11   12
## 3    8   12   13    8   13   11  11    6    8    8    1    8   10   12
## 4   10   14   13   11   14   11  12    6    8   11    1    9   14   14
## 5   13   14   15   12   16   11  14    6   10   14   NA    8   15   16
## 6   14   13   15   11   16   11  14    6   10   14   NA    9   15   16
## 7   12   10   14   11   15   12  14    7   11   13   NA    9   13   15
##   Shum Cycl Pris Arwe Obi Dodg Nina Bone Pene Dant Schm Ella Alla Valk
## 2   13    9    8   10  14    8   10    5   16    7    9    6    6    5
## 3   13   11    9   11  15    8    9    6   17    6   10    3    5    6
## 4   13   13   11   11  16    8    9    8   21    7   11    4   10    8
## 5   13   14   12   13  16    8    8    9   20    7   12    5   11   11
## 6   11   14   12   12  16    9    8    9   20    7   12    5   11   10
## 7    8   14   12   12  13    6    7    8   19    5   10    7   10   11
##   Kins Laya Keit Yoda Clou Tren nEvents         windowstart
## 2    3    7   NA   NA   NA   NA     503 2015-07-01 12:32:19
## 3    5    9   NA   NA   NA   NA     464 2015-07-11 12:32:19
## 4    5    9   NA   NA   NA   NA     542 2015-07-21 12:32:19
## 5    5    9   NA   NA   NA   NA     612 2015-07-31 12:32:19
## 6    5    9   NA   NA   NA   NA     582 2015-08-10 12:32:19
## 7    6    8   NA   NA   NA   NA     523 2015-08-20 12:32:19
##             windowend
## 2 2015-08-30 12:32:19
## 3 2015-09-09 12:32:19
## 4 2015-09-19 12:32:19
## 5 2015-09-29 12:32:19
## 6 2015-10-09 12:32:19
## 7 2015-10-19 12:32:19

Plot node level changes

nodeTS.plot(node.values)

Extract dyad level measures through time.

It is also possible to look at how relationships between two individuals change in time. This is the dyadic level. Here we look at the strength of each dyad trough time, i.e. their number of interactions. A measureFun for dyadic measures should be a function that takes one network and returns a value for each dyad. Names should be associated with each value to ensure that values are associated with the correct dyad. An example is provided below.

#1. create a small function
my.function.dyads <- function(graph){
  
  #calculate some measure from the graph
  my.value <- E(graph)$weight
  
  #assign each weight the correct dyad name
  names(my.value) <- paste(get.edgelist(graph)[, 1], get.edgelist(graph)[, 
        2], sep = "_")
  
  #return the values 
  return(((my.value)))
  
}


#2. extract values through time
dyad.values <- dyadTS(groomEvents, windowsize = days(60), windowshift = days(10), measureFun = my.function.dyads, directed=TRUE)
## [1] "45 networks extracted"
#3. take a look at the output
dyad.values[1:10,1:5]
##    Laur_Malc Malc_Laur Ubun_Wall Wall_Ubun Dott_Jasm
## 2          1         2         1         1         7
## 3         NA         1         2         2         4
## 4         NA         1         2         2         3
## 5          1         2         2         2         3
## 6          1         2         2         2         3
## 7          1         1         2         3         2
## 8          1         1         2         3         4
## 9          1         1        NA         1         4
## 10         1         1        NA         1         4
## 11        NA        NA        NA         1         4

Plot dyad level changes

dyadTS.plot(dyad.values)