Knecht Vignette

Vignette Info and Introduction

This vignette uses the Knecht data from Knecht (2006) and Knecht (2008) to provide an illustrative example of estimating an ego-Temporal Exponential Random Graph Model (ego-TERGM) using the egoTERGM package [@knecht2006networks]. It begins by estimating an ego-TERGM on the Knecht friendship network, a network of 26 students in a Dutch classroom measured across four time-periods. In addition to data on the friendships between students there is nodal attribute data on a variety of demographic and behavioral factors. For a detailed explanation of the data, I refer the reader to the original publications on the data or to the xergm.common help page for the knecht data: ??knecht.

Much of the code for estimating the ego-TERGM is a modification of code originally produced for its cross-sectional equivalent [@salter2015role]. This vignette will proceed step-by-step in presenting the typical workflow for estimating and interpreting an ego-TERGM using egoTERGM.

Note: The code presented here is not built given the runtime for the ego-TERGM presented here. As such, the code presented is purely illustrative. It will successfully run, however.

Importing Knecht Network

The following chunk of code imports the Knecht friendship network gathered by Andrea Knecht and provided in the xergm.common package [@leifeld2014xergm, leifeld2017temporal]. It also uses some code from the xergm.common package to prepare the network for the ego_tergm function, note that it produces a list of network objects.

library(xergm.common)

set.seed(1)

data("knecht")

for (i in 1:length(friendship)) {
  rownames(friendship[[i]]) <- paste("Student.", 1:nrow(friendship[[i]]), sep="")
  colnames(friendship[[i]]) <- paste("Student.", 1:nrow(friendship[[i]]), sep="")
}
rownames(primary) <- rownames(friendship[[1]])
colnames(primary) <- colnames(friendship[[1]])
sex <- demographics$sex
names(sex) <- rownames(friendship[[1]])

# step 2: imputation of NAs and removal of absent nodes:
friendship <- xergm.common::handleMissings(friendship, na = 10, method = "remove")
friendship <- xergm.common::handleMissings(friendship, na = NA, method = "fillmode")

# step 3: add nodal covariates to the networks
for (i in 1:length(friendship)) {
  s <- xergm.common::adjust(sex, friendship[[i]])
  friendship[[i]] <- network::network(friendship[[i]])
  friendship[[i]] <- network::set.vertex.attribute(friendship[[i]], "sex", s)
  idegsqrt <- sqrt(sna::degree(friendship[[i]], cmode = "indegree"))
  friendship[[i]] <- network::set.vertex.attribute(friendship[[i]],
                                                   "idegsqrt", idegsqrt)
  odegsqrt <- sqrt(sna::degree(friendship[[i]], cmode = "outdegree"))
  friendship[[i]] <- network::set.vertex.attribute(friendship[[i]],
                                                   "odegsqrt", odegsqrt)
}
sapply(friendship, network::network.size)

net <- friendship
rm(list=setdiff(ls(), "net"))

Estimation of ego-TERGM

Once the data is imported and transformed into a list of network objects with relevant attributes appended to each network in that list, we can proceed with estimating the ego-TERGM using ego_tergm. Underneath the hood, quite a bit is occuring when the user calls this function. First, the function transforms the list of longitudinally observed networks into a list of longitudinally observed ego-networks. From that point, the initialization proceedure described by Campbell (2018) is used, including the estimation of a TERGM via bootstrapped pseudolikelihood and subsequent clustering of TERGM parameters using k-means clustering [@campbell2018detecting]. Upon initialization, an Expectation Maximization (EM) algorithm is used to find group-centroids and role assignments.

The ego_tergm function requires a few arguments:

library(egoTERGM)
ego_tergm_fit <- ego_tergm(net = net,
                           form = c("edges", "mutual", "triangle", "nodeicov('idegsqrt')", 
                                    "nodeocov('odegsqrt')",  "nodematch('sex')"),
                           core_size = 1,
                           min_size = 5,
                           roles = 3,
                           add_drop = TRUE,
                           directed = TRUE,
                           edge_covariates = FALSE,
                           seed = 12345,
                           R = 10,
                           forking = FALSE,
                           ncpus = 1,
                           steps = 50,
                           tol = 1e-06)

Interpreting ego-TERGM Output

Once the ego-TERGM is fit using the ego_tergm function, there are two auxilliary functions that can be used to assist in interpreting model results. First, I have provided an interpret_ego_tegm function that cleans up the group-based centroids estimated. A warning message is coded into the function that emphasizes that these centroids should not be interpreted as TERGM parameters, but instead, as a means of understanding the distinctions between role assignments. Second, there is a plot_ego_tergm function that plots the role assignments for the reduced networks. The code is as follows.

interpret_ego_tergm(ego_tergm_fit = ego_tergm_fit)

plots <- plot_ego_tergm(ego_tergm_fit = ego_tergm_fit)
plots[[1]]

Assessing Role Generative Structure

To assist in interpreting the role generative structure of role assignments, I have included a simple function, prepare_for_tergm, that takes the output of an ego_tergm call and transforms it into a format that can be used by the btergm function [@leifeld2017temporal]. The code for this is as follows:

net_list <- prepare_for_tergm(ego_tergm_fit = ego_tergm_fit)

# Indexing of the output for prepare_for_tergm refers to the 
# role numbering from initial ego_tergm_fit
role1_btergm <- btergm(net_list[[1]] ~ edges + mutual + triangle + nodeicov('idegsqrt') +
                                        nodeocov('odegsqrt') + nodematch('sex'),
                        R = 500)

# You could then continue this for all remaining network sets
# in net_list

References



Try the egoTERGM package in your browser

Any scripts or data that you put into this service are public.

egoTERGM documentation built on May 17, 2019, 5:03 p.m.