# loadedNamespaces()
# unloadNamespace("ergm")
# unloadNamespace("statnet.common")
master_lib <- "~/R/GHmaster-library"
# #Make lib 1st position in libPath
# defaultPaths <- .libPaths()
# .libPaths(c(master_lib, defaultPaths))
# .libPaths()
#devtools::dev_mode(on=T, path = .libPaths()[1])
#library(network)
#library(ergm)
library(tergm, lib.loc = master_lib)
library(tsna)
sessioninfo::package_info(pkgs = c("statnet.common", "network", "rle",
"ergm", "tergm"),
dependencies = FALSE) package * version date lib
ergm * 4.0-6512 2021-06-22 [1]
network * 1.17.1-685 2021-06-16 [1]
rle 0.9.2-234 2021-06-16 [1]
statnet.common 4.5.0-362 2021-06-16 [1]
tergm * 4.0-2301 2021-06-22 [1]
source
Github (statnet/ergm@763ddda)
Github (statnet/network@253413a)
Github (statnet/rle@d08b185)
Github (statnet/statnet.common@e3c23c1)
Github (statnet/tergm@eac9f3b)
[1] C:/Users/Martina Morris/Documents/R/GHmaster-library
[2] C:/Users/Martina Morris/Documents/R/win-library/4.0
[3] C:/Program Files/R/R-4.0.5/library
Standard network summary
data(samplk)
samplk1 Network attributes:
vertices = 18
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
total edges= 55
missing edges= 0
non-missing edges= 55
Vertex attribute names:
cloisterville group vertex.names
No edge attributes
Replicates the standard summary for each network
# summary shows the nodes & edges at each slice
samp.list <- list(samplk1,samplk2,samplk3)
samp.list[[1]]
Network attributes:
vertices = 18
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
total edges= 55
missing edges= 0
non-missing edges= 55
Vertex attribute names:
cloisterville group vertex.names
No edge attributes
[[2]]
Network attributes:
vertices = 18
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
total edges= 57
missing edges= 0
non-missing edges= 57
Vertex attribute names:
cloisterville group vertex.names
No edge attributes
[[3]]
Network attributes:
vertices = 18
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
total edges= 56
missing edges= 0
non-missing edges= 56
Vertex attribute names:
cloisterville group vertex.names
No edge attributes
Only shows us that there are 3 network objects in this list
# summary only shows there are 3 network objects as components
samp.netlist <- network.list(samp.list)
samp.netlistNumber of Networks: 3
Summary shows what tergm will send to ergm for term construction and estimation: the sum of the second and third neworks.
# summary shows nodes(2) + nodes(3), and edges(2) + edges(3)
samp.series <- NetSeries(samp.list)
samp.series Combined 2 networks on '.NetworkID':
1: n = 18, directed = TRUE, bipartite = FALSE, loops = FALSE
2: n = 18, directed = TRUE, bipartite = FALSE, loops = FALSE
Network attributes:
vertices = 36
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
ergm:
constraints: ~blockdiag(".NetworkID") + discord(.PrevNet)
total edges= 113
missing edges= 0
non-missing edges= 113
Vertex attribute names:
.NetworkID .NetworkName cloisterville group vertex.names
No edge attributes
Summary shows the unique total node and edgecount (verified with the collapsed version).
# summary shows the unique # nodes and edges in both cases
# we start at 1 to make the series index consistent with the other
# network storage mechanisms
samp.dyn <- networkDynamic(network.list = samp.list, start=1)Onsets and termini not specified, assuming each network in network.list should have a discrete spell of length 1
Argument base.net not specified, using first element of network.list instead
Created net.obs.period to describe network
Network observation period info:
Number of observation spells: 1
Maximal time range observed: 1 until 4
Temporal mode: discrete
Time unit: step
Suggested time increment: 1
samp.dynNetworkDynamic properties:
distinct change times: 4
maximal time range: 1 until 4
Includes optional net.obs.period attribute:
Network observation period info:
Number of observation spells: 1
Maximal time range observed: 1 until 4
Temporal mode: discrete
Time unit: step
Suggested time increment: 1
Network attributes:
vertices = 18
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
net.obs.period: (not shown)
total edges= 88
missing edges= 0
non-missing edges= 88
Vertex attribute names:
active cloisterville group vertex.names
Edge attribute names:
active
samp.collapse <- network.collapse(samp.dyn, onset=1, terminus=4)
samp.collapse Network attributes:
vertices = 18
directed = TRUE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
total edges= 88
missing edges= 0
non-missing edges= 88
Vertex attribute names:
cloisterville group vertex.names
No edge attributes
These replicate the edge counts performed by the operators, which makes it easier to verify. But it only works for 2 panels. Show the code for more info.
form = network.edgecount(samplk1 | samplk2)
persist = network.edgecount(samplk1 & samplk2)
diss = -persist
dissolved = network.edgecount(samplk1) - persist
cross = network.edgecount(samplk2)
change = network.edgecount(xor(samplk1, samplk2))
cbind(form=form, persist=persist, diss=diss, dissolved=dissolved,
cross=cross, change=change) form persist diss dissolved cross change
[1,] 77 35 -35 20 57 42
Cross sectional stats and form/diss changes from tsna
samp.stats <- cbind(edges = tErgmStats(samp.dyn, "~edges"),
form = tEdgeFormation(samp.dyn),
diss = tEdgeDissolution(samp.dyn))
samp.statsTime Series:
Start = 1
End = 4
Frequency = 1
edges form diss
1 55 55 0
2 57 22 20
3 56 16 17
4 0 0 56
These will be model-specific. So we’ll show results for different specifications.
Form + DissWorks on NetSeries and nD (but not lists or netlists), and results are very different for these two, because they represent the network differently.
# summary.list <- summary(samp.list ~
# Form(~edges) +
# Diss(~edges))
#
# summary.netlist <- summary(samp.netlist ~
# Form(~edges) +
# Diss(~edges))
summary.fd.series <- summary(samp.series ~
Form(~edges) +
Diss(~edges))
summary.fd.seriesForm~edges Diss~edges
150 -75
summary.fd.nD <- summary(samp.dyn ~
Form(~edges) +
Diss(~edges),
at=0:3)
summary.fd.nD Form~edges Diss~edges
[1,] 0 0
[2,] 55 0
[3,] 77 -35
[4,] 73 -40
Works for all data structures
fit.fd.list <- tergm(
samp.list ~
Form(~edges) +
Diss(~edges),
estimate = "CMLE", times = c(1:3)
)
fit.fd.netlist <- tergm(
samp.netlist ~
Form(~edges) +
Diss(~edges),
estimate = "CMLE", times = c(1:3)
)
fit.fd.series <- tergm(
samp.series ~
Form(~edges) +
Diss(~edges),
estimate = "CMLE" #, times = c(1:3)
)
fit.fd.nD <- tergm(
samp.dyn ~
Form(~edges) +
Diss(~edges),
estimate = "CMLE", times = c(1:3)
)All give the same output.
cat("Coefs")Coefs
rbind(list=coef(fit.fd.list),
netlist = coef(fit.fd.netlist),
netseries = coef(fit.fd.series),
nD=coef(fit.fd.nD)) Form~edges Diss~edges
list -2.497979 -0.7065702
netlist -2.497979 -0.7065702
netseries -2.497979 -0.7065702
nD -2.497979 -0.7065702
cat("nw.stats")nw.stats
rbind(list=fit.fd.list$nw.stats,
netlist = fit.fd.netlist$nw.stats,
netseries = fit.fd.series$nw.stats,
nD= fit.fd.nD$nw.stats) Form~edges Diss~edges
list 150 -75
netlist 150 -75
netseries 150 -75
nD 150 -75
Form + PersistWorks on NetSeries and nD (but not lists or netlists), and results are very different for these two, because they represent the network differently.
# summary.list <- summary(samp.list ~
# Form(~edges) +
# Persist(~edges))
#
# summary.netlist <- summary(samp.netlist ~
# Form(~edges) +
# Persist(~edges))
summary.fp.series <- summary(samp.series ~
Form(~edges) +
Persist(~edges))
summary.fp.series Form~edges Persist~edges
150 75
summary.fp.nD <- summary(samp.dyn ~
Form(~edges) +
Persist(~edges),
at=0:3)
summary.fp.nD Form~edges Persist~edges
[1,] 0 0
[2,] 55 0
[3,] 77 35
[4,] 73 40
Works for all data structures
fit.fp.list <- tergm(
samp.list ~
Form(~edges) +
Persist(~edges),
estimate = "CMLE", times = c(1:3)
)
fit.fp.netlist <- tergm(
samp.netlist ~
Form(~edges) +
Persist(~edges),
estimate = "CMLE", times = c(1:3)
)
fit.fp.series <- tergm(
samp.series ~
Form(~edges) +
Persist(~edges),
estimate = "CMLE" #, times = c(1:3)
)
fit.fp.nD <- tergm(
samp.dyn ~
Form(~edges) +
Persist(~edges),
estimate = "CMLE", times = c(1:3)
)All give the same output.
cat("Coefs")Coefs
rbind(list=coef(fit.fp.list),
netlist = coef(fit.fp.netlist),
netseries = coef(fit.fp.series),
nD=coef(fit.fp.nD)) Form~edges Persist~edges
list -2.497979 0.7065702
netlist -2.497979 0.7065702
netseries -2.497979 0.7065702
nD -2.497979 0.7065702
cat("nw.stats")nw.stats
rbind(list=fit.fp.list$nw.stats,
netlist = fit.fp.netlist$nw.stats,
netseries = fit.fp.series$nw.stats,
nD= fit.fp.nD$nw.stats) Form~edges Persist~edges
list 150 75
netlist 150 75
netseries 150 75
nD 150 75
Cross + ChangeWorks on NetSeries and nD (but not lists or netlists), and results are very different for these two, because they represent the network differently.
# summary.list <- summary(samp.list ~
# Form(~edges) +
# Persist(~edges))
#
# summary.netlist <- summary(samp.netlist ~
# Form(~edges) +
# Persist(~edges))
summary.cc.series <- summary(samp.series ~
Cross(~edges) +
Change(~edges))
summary.cc.series edges Change~edges
113 75
summary.cc.nD <- summary(samp.dyn ~
Cross(~edges) +
Change(~edges),
at=0:3)
summary.cc.nD Passthrough~edges Change~edges
[1,] 0 0
[2,] 55 55
[3,] 57 42
[4,] 56 33
Works for all data structures
fit.cc.list <- tergm(
samp.list ~
Cross(~edges) +
Change(~edges),
estimate = "CMLE", times = c(1:3)
)
fit.cc.netlist <- tergm(
samp.netlist ~
Cross(~edges) +
Change(~edges),
estimate = "CMLE", times = c(1:3)
)
fit.cc.series <- tergm(
samp.series ~
Cross(~edges) +
Change(~edges),
estimate = "CMLE" #, times = c(1:3)
)
fit.cc.nD <- tergm(
samp.dyn ~
Cross(~edges) +
Change(~edges),
estimate = "CMLE", times = c(1:3)
)All give the same output.
cat("Coefs")Coefs
rbind(list=coef(fit.cc.list),
netlist = coef(fit.cc.netlist),
netseries = coef(fit.cc.series),
nD=coef(fit.cc.nD)) edges Change~edges
list -0.8957043 -1.602274
netlist -0.8957043 -1.602274
netseries -0.8957043 -1.602274
nD -0.8957043 -1.602274
cat("nw.stats")nw.stats
rbind(list=fit.cc.list$nw.stats,
netlist = fit.cc.netlist$nw.stats,
netseries = fit.cc.series$nw.stats,
nD= fit.cc.nD$nw.stats) edges Change~edges
list 113 75
netlist 113 75
netseries 113 75
nD 113 75
Works on NetSeries and nD (but not lists or netlists), and results are very different for these two, because they represent the network differently.
# summary.list <- summary(samp.list ~
# Form(~edges) +
# Persist(~edges))
#
# summary.netlist <- summary(samp.netlist ~
# Form(~edges) +
# Persist(~edges))
summary.none.series <- summary(samp.series ~ edges)
summary.none.seriesedges
113
summary.none.nD <- summary(samp.dyn ~ edges,
at=0:3)
summary.none.nD [,1]
edges 0
edges 55
edges 57
edges 56
Works for all data structures
fit.none.list <- tergm(
samp.list ~edges,
estimate = "CMLE", times = c(1:3)
)
fit.none.netlist <- tergm(
samp.netlist ~edges,
estimate = "CMLE", times = c(1:3)
)
fit.none.series <- tergm(
samp.series ~ edges,
estimate = "CMLE" #, times = c(1:3)
)
fit.none.nD <- tergm(
samp.dyn ~ edges,
estimate = "CMLE", times = c(1:3)
)All give the same output.
cat("Coefs")Coefs
rbind(list=coef(fit.none.list),
netlist = coef(fit.none.netlist),
netseries = coef(fit.none.series),
nD=coef(fit.none.nD)) edges
list -1.485218
netlist -1.485218
netseries -1.485218
nD -1.485218
cat("nw.stats")nw.stats
rbind(list=fit.none.list$nw.stats,
netlist = fit.none.netlist$nw.stats,
netseries = fit.none.series$nw.stats,
nD= fit.none.nD$nw.stats) edges
list 113
netlist 113
netseries 113
nD 113
The simple descriptives:
samp.statsTime Series:
Start = 1
End = 4
Frequency = 1
edges form diss
1 55 55 0
2 57 22 20
3 56 16 17
4 0 0 56
test <- rbind(names(coef(fit.cc.nD)), round(coef(fit.cc.nD), 3))The model stats for each model
| model | names | nw.stats |
|---|---|---|
| Form + Diss: | Form~edges, Diss~edges | 150, -75 |
| Form + Persist: | Form~edges, Persist~edges | 150, 75 |
| Cross + Change: | edges, Change~edges | 113, 75 |
| no operators: | edges | 113 |
The model coefs for each model
| model | names | coefs |
|---|---|---|
| Form + Diss: | Form~edges, Diss~edges | -2.498, -0.707 |
| Form + Persist: | Form~edges, Persist~edges | -2.498, 0.707 |
| Cross + Change: | edges, Change~edges | -0.896, -1.602 |
| no operators: | edges | -1.485 |
Note that:
The Form + Persist coefs are: -2.498, 0.707
The Cross + Change coefs are: -0.896, -1.602
-2.498 = -1.602 + (-0.896), so Form = Cross + Change (Form operates on the union)
0.707 = -0.896 - (-1.602), so Persist = Change - Cross (Persist operates on the intersection)
And from Pavel:
When there are 3 time points, both Cross() and bare terms will not “see” the first network. t1 network will only affect Change(), Form(), and Diss()/Persist().