knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
#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)
The netTS package is meant for relational data that takes place through time. Generally, when constructing social networks to interogate relational data, some amount of aggregation is required. E.g. group all data into years to create yearly networks. The point of this package is to facilitate this process of aggregation, using a moving window approach.
The moving window 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.
This data is the rquired format for working with netTS. The first two coloumns should have information about what two 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)
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). The measureFun input should be a function that takes as input an igraph network and returns one value. Here custom functions can be used. There are also some functions already in netTS that might be useful.
The idea of using functions here is to provide flexibility to users, 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.
#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) #3. Take a look at the outputs head(graph.values)
Plot the graph level measures through time
#1. Plot the results ggplot(graph.values, aes(x=windowstart, y=measure))+geom_point()+geom_line()+labs(y="Mean degree",x="Date")+theme_classic()
It is then possible to test whether these measures differ from randomly permutated networks.
The perumation used here randomly swaps individuals in the events dataframe. Again there are prespecified options for performin permutaitons, but as it is often useful to specify eactly how a network is permuted users can specify their own permutation functions. The results of this permutation below suggest that the network shows lower mean degree than expected due to chance arrangement of events, i.e., individuals groom fewer partners than expected if grooming was random.
#1. Estimate the observed network measures and the range expected when permuted. Notes: 1 - a subset of the data and a small value for the number of permutation here is chosen here as the process is slow, and 2 - see perumtation vignette for more options when using permutation tests. graph.values <- graphTS(groomEvents[1:1500,], windowsize = days(60), windowshift = days(10), measureFun = my.function.net, directed=TRUE, nperm = 100) #2. Plot the results ggplot(graph.values, aes(x=windowstart, y=measure))+geom_point()+geom_line()+ geom_ribbon(data=graph.values, aes(ymin=CI.low, ymax=CI.high), fill="red", alpha=0.2)+ labs(y="Mean out degree",x="Date")+theme_classic()
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. Names should be associated with each value to ensure that values are associated with the correct 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) #3. Take a look at the output head(node.values)
Plot node level changes
#1. Convert the dataframe from wide to long format df.node.values <- melt(node.values, id.vars = c("windowstart","windowend", "nEvents" )) names(df.node.values)[names(df.node.values)=="variable"] <- "node" names(df.node.values)[names(df.node.values)=="value"] <- "measure" #2. Plot the results ggplot(df.node.values, aes(x=windowstart, y=measure, col=node))+geom_line() + theme_classic() + labs(y="Mean degree",x="Date")
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 node. 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 to the correct dyad 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) #3. take a look at the output dyad.values[1:10,1:5]
Plot dyad level changes
#1. convert the dataframe from wide to long format df.dyad.values <- melt(dyad.values, id.vars = c("windowstart","windowend", "nEvents" )) names(df.dyad.values)[names(df.dyad.values)=="variable"] <- "dyad" names(df.dyad.values)[names(df.dyad.values)=="value"] <- "measure" #2. plot the results ggplot(df.dyad.values, aes(x=windowstart, y=measure, col=dyad))+geom_line() + theme_classic() + labs(y="Weight",x="Date") + theme(legend.position="none",legend.text = element_text(size=6))
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.