There are a lot of cases in this world that can be represented as a graph/network. But sometimes that network is not static, which means it changes over time. This kind of network is called ‘dynamic network’ (or ‘temporal network’ sometimes). Since it is usually observed in social network, the analysis through dynamic network is called “(Temporal) Social Network Analysis” sometimes . Some examples of real-life dynamic network are: friendship network, business connection network, the network of biological interaction between organisms, Traffic/Access network,etc. The time intervention here does not allow us to use the algorithm, analysis, and tools the same as the ordinary network-analysis one.
I will introduce some important package in R specifically for Dynamic Network Analysis and Visualization. There are two important packages here: tsna
(Temporal Social Network Analysis) and ndtv
(Network Dynamic Temporal Visualization). The tsna
package consist functionality to analyse temporal network, it is the extension of sna
package. The ndtv
package was built to render temporal network data as movies, interactive animations, or any other representations of changing relational structures and attributes. In order to work with the network animations in ndtv
, we better understand Statnet
’s dynamic network format (Statnet
is a family packages, including network
, sna
, ergm
, stergm
, and others).
Here I use ‘short.stergm.sim’ dataset from ndtv
package. This dataset is a simulation data based on a network of business connections among Renaissance Florentine families.
library(ndtv)
## Warning: package 'ndtv' was built under R version 3.6.1
## Loading required package: network
## Warning: package 'network' was built under R version 3.6.1
## network: Classes for Relational Data
## Version 1.15 created on 2019-04-01.
## copyright (c) 2005, Carter T. Butts, University of California-Irvine
## Mark S. Handcock, University of California -- Los Angeles
## David R. Hunter, Penn State University
## Martina Morris, University of Washington
## Skye Bender-deMoll, University of Washington
## For citation information, type citation("network").
## Type help("network-package") to get started.
## Loading required package: networkDynamic
## Warning: package 'networkDynamic' was built under R version 3.6.1
##
## networkDynamic: version 0.10.0, created on 2019-04-04
## Copyright (c) 2019, Carter T. Butts, University of California -- Irvine
## Ayn Leslie-Cook, University of Washington
## Pavel N. Krivitsky, University of Wollongong
## Skye Bender-deMoll, University of Washington
## with contributions from
## Zack Almquist, University of California -- Irvine
## David R. Hunter, Penn State University
## Li Wang
## Kirk Li, University of Washington
## Steven M. Goodreau, University of Washington
## Jeffrey Horner
## Martina Morris, University of Washington
## Based on "statnet" project software (statnet.org).
## For license and citation information see statnet.org/attribution
## or type citation("networkDynamic").
## Loading required package: animation
## Loading required package: sna
## Warning: package 'sna' was built under R version 3.6.1
## Loading required package: statnet.common
## Warning: package 'statnet.common' was built under R version 3.6.1
##
## Attaching package: 'statnet.common'
## The following object is masked from 'package:base':
##
## order
## sna: Tools for Social Network Analysis
## Version 2.4 created on 2016-07-23.
## copyright (c) 2005, Carter T. Butts, University of California-Irvine
## For citation information, type citation("sna").
## Type help(package="sna") to get started.
## Registered S3 method overwritten by 'openssl':
## method from
## print.bytes Rcpp
##
## ndtv: version 0.13.0, created on 2019-05-21
## Copyright (c) 2019, Skye Bender-deMoll, University of Washington
## with contributions from
## Martina Morris, University of Washington
## Based on "statnet" project software (statnet.org).
## For license and citation information see statnet.org/attribution
## or type citation("ndtv").
data(short.stergm.sim)
head(as.data.frame(short.stergm.sim))
## onset terminus tail head onset.censored terminus.censored duration
## 1 0 1 3 5 FALSE FALSE 1
## 2 10 20 3 5 FALSE FALSE 10
## 3 0 25 3 6 FALSE FALSE 25
## 4 0 1 3 9 FALSE FALSE 1
## 5 2 25 3 9 FALSE FALSE 23
## 6 0 4 3 11 FALSE FALSE 4
## edge.id
## 1 1
## 2 1
## 3 2
## 4 3
## 5 3
## 6 4
As you can see, the dataset contain some important variables as follow:
- onset
: The beginning time point of the relation,
- terminus
: The end time point of the relation,
- tail
: the origin vertex,
- head
: the terminal vertex,
- duration
: the duration of the relation.
First, we want to plot the network (ignoring the time point) as follows.
plot(short.stergm.sim)
We can also plot the network at some time-point. In this case we need network.extract()
function.
plot(network.extract(short.stergm.sim,at=5))
We can also plot the network in some duration of time. Here there are two variation of plotting:
(1.) plot any edge/relation that happen at some time-point in given duration of time, or
(2.) plot the edge/relation that happen at the entire given duration of time. Let we see what’s the difference.
# for (1.)
plot(network.extract(short.stergm.sim,onset=1,terminus=5,rule = "any"))
# for (2.)
plot(network.extract(short.stergm.sim,onset=1,terminus=5,rule = "all"))
Lastly, we can also render a movie about our network to see how it changes over time.
# Change the output.mode to JSON or HTML to see the difference
render.d3movie(short.stergm.sim,displaylabels=TRUE,output.mode = "htmlWidget")
## No slice.par found, using
## slice parameters:
## start:0
## end:25
## interval:1
## aggregate.dur:1
## rule:latest
## Calculating layout for network slice from time 0 to 1
## Calculating layout for network slice from time 1 to 2
## Calculating layout for network slice from time 2 to 3
## Calculating layout for network slice from time 3 to 4
## Calculating layout for network slice from time 4 to 5
## Calculating layout for network slice from time 5 to 6
## Calculating layout for network slice from time 6 to 7
## Calculating layout for network slice from time 7 to 8
## Calculating layout for network slice from time 8 to 9
## Calculating layout for network slice from time 9 to 10
## Calculating layout for network slice from time 10 to 11
## Calculating layout for network slice from time 11 to 12
## Calculating layout for network slice from time 12 to 13
## Calculating layout for network slice from time 13 to 14
## Calculating layout for network slice from time 14 to 15
## Calculating layout for network slice from time 15 to 16
## Calculating layout for network slice from time 16 to 17
## Calculating layout for network slice from time 17 to 18
## Calculating layout for network slice from time 18 to 19
## Calculating layout for network slice from time 19 to 20
## Calculating layout for network slice from time 20 to 21
## Calculating layout for network slice from time 21 to 22
## Calculating layout for network slice from time 22 to 23
## Calculating layout for network slice from time 23 to 24
## Calculating layout for network slice from time 24 to 25
## Calculating layout for network slice from time 25 to 26
## caching 10 properties for slice 0
## caching 10 properties for slice 1
## caching 10 properties for slice 2
## caching 10 properties for slice 3
## caching 10 properties for slice 4
## caching 10 properties for slice 5
## caching 10 properties for slice 6
## caching 10 properties for slice 7
## caching 10 properties for slice 8
## caching 10 properties for slice 9
## caching 10 properties for slice 10
## caching 10 properties for slice 11
## caching 10 properties for slice 12
## caching 10 properties for slice 13
## caching 10 properties for slice 14
## caching 10 properties for slice 15
## caching 10 properties for slice 16
## caching 10 properties for slice 17
## caching 10 properties for slice 18
## caching 10 properties for slice 19
## caching 10 properties for slice 20
## caching 10 properties for slice 21
## caching 10 properties for slice 22
## caching 10 properties for slice 23
## caching 10 properties for slice 24
## caching 10 properties for slice 25
## Loading required namespace: htmlwidgets
## loading ndtv-d3 animation widget...
That’s all the brief introduction of the ndtv
package. Now we will explore some of supporting algorithm from tsna
package.
library(tsna)
## Warning: package 'tsna' was built under R version 3.6.1
plot(tEdgeFormation(short.stergm.sim, time.interval = 1))
Here we can observe that there is a high spike in edge formation at the time-point 13, this implies that the business connections are raised here.
dynamicBetweenness <- tSnaStats(
short.stergm.sim,
snafun = "centralization",
start = 1,
end = 25,
time.interval = 1,
aggregate.dur = 0, # The duration that you think 'seasonality' exist.
FUN = "betweenness"
)
plot(dynamicBetweenness)
Since the centrality measurement here is using ‘betweeness’, we can say that around time-point 3 and around time-point 14 there is a big network component with some family having important role in mantaining connectivity between other family.
The last property that we want to observe are ‘Temporal reachable set’ and ‘Temporal path’.
Sometimes, we also want to know how many vertices can be “reached” by one vertex or how many vertices can “reach” that vertex in the entire period of time. tReach
function will give us information about that. The term ‘reach’ here maybe a bit confusing, it will be clearer to understand in the ‘temporal path’ section. There is two variation about direction
parameter here:
Forward: It will count how many vertices that can be reached by certain vertex (means: this vertex is the ‘tail’ vertex in directed network).
Since we interpret the network as undirected network in short.stergn.sim
dataset (business connection suppose to be mutual), the direction backward and forward clearly give us the same result. The ‘index’ axis in plot below stands for vertex.id and the y-axis visualize how many vertices that connected to it through temporal path (including itself).
plot(tReach(short.stergm.sim,direction="bkwd"))
plot(tReach(short.stergm.sim,direction = "fwd"))
In order to see the phenomenon clearly, let we use tPath
function to visualize all feasible (forward/backward) temporal path that are started/ended at a desired vertex. Here I visualize the feasible forward temporal path that start from “Ridolfi” (vertex id=13). From the visualization below, we can observe that “Ridolfi” and “Tournabouni” are connected by ‘temporal path’. The temporal path here can be illustrated as follows.
Suppose that Ridolfi family want to send some important business contract to Tornabuoni family. Ridolfi family need to send it between time-point 1 to 25 and since they are not directly connected, Ridolfi family need to send it via one of their business connection and pass it to other business connected family until it arrives at Tournabouni family. The problem is: Can this method be done? The answer is “YES”. Observe that at time-point of 13, Ridolfi is connected to Barbadori and at the exact time, Barbadori is connected to Lamberteschi. Lamberteschi family need to keep the contract with them until the time-point of 21 and pass it to Tournabouni family. Yes, this route is called “Temporal path”. Here we can also observe that Ridolfi family cannot send a contract to Albizzi family using the same method, since there is no temporal path from Ridolfi to Albizzi.
set.seed(100)
RidolfiFwdPath <- tPath(
short.stergm.sim,
v = 13,
direction = "fwd"
)
plotPaths(
short.stergm.sim,
RidolfiFwdPath,
displaylabels = T,
vertex.col = "white"
)
Reference:
- https://kateto.net/network-visualization
- https://programminghistorian.org/en/lessons/temporal-network-analysis-with-r#fnref:2