knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

Install netTS, load some 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)

Introduction

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.

Look at some example data

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)

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). 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()

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. 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")

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 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))


tbonne/netTS documentation built on July 26, 2021, 2:27 a.m.