# Load required packages
library(RSiena)
## Warning: package 'RSiena' was built under R version 4.4.3
library(statnet)
## Warning: package 'statnet' was built under R version 4.4.3
## Loading required package: tergm
## Warning: package 'tergm' was built under R version 4.4.3
## Loading required package: ergm
## Warning: package 'ergm' was built under R version 4.4.3
## Loading required package: network
## Warning: package 'network' was built under R version 4.4.3
##
## 'network' 1.19.0 (2024-12-08), part of the Statnet Project
## * 'news(package="network")' for changes since last version
## * 'citation("network")' for citation information
## * 'https://statnet.org' for help, support, and other information
##
## 'ergm' 4.8.1 (2025-01-20), part of the Statnet Project
## * 'news(package="ergm")' for changes since last version
## * 'citation("ergm")' for citation information
## * 'https://statnet.org' for help, support, and other information
## 'ergm' 4 is a major update that introduces some backwards-incompatible
## changes. Please type 'news(package="ergm")' for a list of major
## changes.
## Loading required package: networkDynamic
## Warning: package 'networkDynamic' was built under R version 4.4.3
##
## 'networkDynamic' 0.11.5 (2024-11-21), part of the Statnet Project
## * 'news(package="networkDynamic")' for changes since last version
## * 'citation("networkDynamic")' for citation information
## * 'https://statnet.org' for help, support, and other information
## Registered S3 method overwritten by 'tergm':
## method from
## simulate_formula.network ergm
##
## 'tergm' 4.2.1 (2024-10-08), part of the Statnet Project
## * 'news(package="tergm")' for changes since last version
## * 'citation("tergm")' for citation information
## * 'https://statnet.org' for help, support, and other information
##
## Attaching package: 'tergm'
## The following object is masked from 'package:ergm':
##
## snctrl
## Loading required package: ergm.count
## Warning: package 'ergm.count' was built under R version 4.4.3
##
## 'ergm.count' 4.1.2 (2024-06-15), part of the Statnet Project
## * 'news(package="ergm.count")' for changes since last version
## * 'citation("ergm.count")' for citation information
## * 'https://statnet.org' for help, support, and other information
## Loading required package: sna
## Warning: package 'sna' was built under R version 4.4.3
## Loading required package: statnet.common
## Warning: package 'statnet.common' was built under R version 4.4.3
##
## Attaching package: 'statnet.common'
## The following object is masked from 'package:ergm':
##
## snctrl
## The following objects are masked from 'package:base':
##
## attr, order
## sna: Tools for Social Network Analysis
## Version 2.8 created on 2024-09-07.
## copyright (c) 2005, Carter T. Butts, University of California-Irvine
## For citation information, type citation("sna").
## Type help(package="sna") to get started.
## Loading required package: tsna
##
## 'statnet' 2019.6 (2019-06-13), part of the Statnet Project
## * 'news(package="statnet")' for changes since last version
## * 'citation("statnet")' for citation information
## * 'https://statnet.org' for help, support, and other information
## unable to reach CRAN
library(igraph)
## Warning: package 'igraph' was built under R version 4.4.3
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:sna':
##
## betweenness, bonpow, closeness, components, degree, dyad.census,
## evcent, hierarchy, is.connected, neighborhood, triad.census
## The following objects are masked from 'package:network':
##
## %c%, %s%, add.edges, add.vertices, delete.edges, delete.vertices,
## get.edge.attribute, get.edges, get.vertex.attribute, is.bipartite,
## is.directed, list.edge.attributes, list.vertex.attributes,
## set.edge.attribute, set.vertex.attribute
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:igraph':
##
## as_data_frame, groups, union
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Load FTA matrix data which record global FTA ties between 1998 and 2019
FTA <- readRDS(url("https://www.dropbox.com/scl/fi/6luyfnrur7ictisun8zxh/FTA19982019.rds?rlkey=h6af5x79e318vm6q7rj8b8loc&st=bpi38ulh&dl=1"))
# Read in country name data, you can see a list of country name, abbreviation, and 3-digit iso code. We need them to index countries in our data
cid <- read.csv(url("https://www.dropbox.com/scl/fi/7isucibr6woxr5gnlthu8/countryid.csv?rlkey=cezf0zg1vbkcvxrrvazzu4pjf&st=uxw2yxdw&dl=1"))
# Convert to matrix format
for(i in 1:length(FTA)){
FTA[[i]] <- as.matrix(FTA[[i]])
# Set country name and transform the adjacency FTA matrix into binary network form
colnames(FTA[[i]]) <- cid$comtrade_id
rownames(FTA[[i]]) <- cid$comtrade_id
}
length(FTA)
## [1] 22
## Stacking FTA outcome network into a multidimensional array. We need FTA matrix from the last five years (2015 to 2019, 22 years!)
FTA2019 <- FTA[[22]]
FTA2018 <- FTA[[21]]
FTA2017 <- FTA[[20]]
FTA2016 <- FTA[[19]]
FTA2015 <- FTA[[18]]
# Quick question. Is global free trade on a secular rise? Let Jaccard index be our guide. Jaccard index is a statistic used for gauging the similarity between two count data. It is defined as: N11 / (N01 + N10 + N11), using FTA_change1819 for illustration, N11 is the number of FTAs existed in both periods (4375), N01 is the number of FTAs that were not in period 1 but were in period 2 (68) and N10 is the number of FTAs that were in period 1 but not in period 2 (0).
FTA_change1819 <- table(FTA[[18]], FTA[[19]])
FTA_change1819 # Similarity in global FTA networks between 2018 and 2019
##
## 0 1
## 0 21546 68
## 1 0 4307
4307/(4307+68)
## [1] 0.9844571
FTA_change1920 <- table(FTA[[19]], FTA[[20]])
FTA_change1920 # Similarity in global FTA networks between 2019 and 2020
##
## 0 1
## 0 21008 538
## 1 0 4375
4375/(4375+538)
## [1] 0.8904946
FTA_change2021 <- table(FTA[[20]], FTA[[21]])
FTA_change2021 # Similarity in global FTA networks between 2020 and 2021
##
## 0 1
## 0 20994 14
## 1 2 4911
4911/(4911+14+2)
## [1] 0.9967526
FTA_change2122 <- table(FTA[[21]], FTA[[22]])
FTA_change2122 # Similarity in global FTA networks between 2021 and 2022
##
## 0 1
## 0 20866 130
## 1 12 4913
4913/(4913+130+12)
## [1] 0.971909
# Well, it seems that the evolution of global free trade is relatively stable.
# Check row and column dimension: is it a square matrix?
nrow(FTA[[2]]) == ncol(FTA[[22]]) # Yes!
## [1] TRUE
net_size = nrow(FTA[[2]])
## Create a FTA array: five years, 161 by 161 observations in each year
FTA_array <- array(c(FTA2019 = FTA[[22]], FTA2019 = FTA[[21]], FTA2019 = FTA[[20]], FTA2019 = FTA[[19]], FTA2019 = FTA[[18]]),
dim = c(net_size, net_size, 5))
dim(FTA_array)
## [1] 161 161 5
## Create SIENA dependent variable network: one-mode network (all edge values are the same, either 0 or 1)
FTA_networks <- sienaDependent(netarray = FTA_array,
type = "oneMode",
allowOnly = FALSE) # Allow the dependent variable to both increase AND decrease
## Load country attributes data. You can see a list of country-level covariates, they will be used as regressors.
country_attr <- readRDS(url("https://www.dropbox.com/scl/fi/ddhf2z5tl9bo8l9jo29vb/country_attr.rds?rlkey=5upfqxcljtuphtuvingnptptm&st=9bc9dddy&dl=1"))
# Take a look at the data, just your average-looking data.frame object
names(country_attr)
## [1] "vertex.names" "cname" "year" "population"
## [5] "industrial_va" "service_va" "trade_open" "polity"
## [9] "execrlc" "liec" "bound_rate" "applied_rate"
## [13] "binding" "kaopen" "ipr" "binding_over"
## [17] "lGDP"
head(country_attr)
## vertex.names cname year population industrial_va service_va trade_open polity
## 1 4 AFG 2015 17.34187 22.12404 53.23529 55.3462 10
## 2 8 ALB 2015 14.88022 21.76366 46.28435 71.8010 20
## 3 24 AGO 2015 17.14772 41.93309 48.65989 62.8885 9
## 4 28 ATG 2015 11.44642 16.45798 69.88088 93.6295 21
## 5 32 ARG 2015 17.57671 23.15306 55.81490 22.4862 20
## 6 51 ARM 2015 14.88022 25.70870 48.21267 71.5933 16
## execrlc liec bound_rate applied_rate binding kaopen ipr binding_over
## 1 0 7 0.00 5.47 0.0 -2 0.0001958417 -5.47
## 2 -1 7 6.79 1.11 100.0 0 0.0040150162 5.68
## 3 -1 6 59.08 9.38 100.0 -2 0.0078045620 49.70
## 4 -1 6 58.75 12.03 97.5 1 0.0036434520 46.72
## 5 -1 7 31.74 7.35 100.0 -2 0.0265864835 24.39
## 6 0 7 8.68 2.93 100.0 2 0.0000000000 5.75
## lGDP
## 1 0.00000000
## 2 0.00000000
## 3 0.00000000
## 4 0.00000000
## 5 0.04520129
## 6 0.04498265
## Create time-varying variables: need to reshape the original data.frame to wide format AND in matrix form
# If you want to use a constant (time-invariant or fixed) variable, then use coCovar()
## Notations ##
#cc = coCovar
#vc = varCovar
#cdc = coDyadCovar
#vdc = varDyadCovar
library(reshape)
## Warning: package 'reshape' was built under R version 4.4.3
##
## Attaching package: 'reshape'
## The following object is masked from 'package:dplyr':
##
## rename
# Population
pop <- reshape(country_attr[, c(1, 4, 3)], idvar = "vertex.names", timevar = "year", direction = "wide")
pop_vc <- varCovar(as.matrix(pop[,-1])) # Make it into time-varying covariate, -1 means remove country id column
# Trade openness
trade_openness <- reshape(country_attr[, c(1, 7, 3)], idvar = "vertex.names", timevar = "year", direction = "wide")
to_vc <- varCovar(as.matrix(trade_openness[,-1])) # Also make it into time-varying covariate
## Create "dyadic" time-varying variables
# First, we need dyadic trade volume data between 2015 and 2019, recorded as log of million USD
trade2015 <- readRDS(url("https://www.dropbox.com/scl/fi/17i8e42xzhgo9dqdmzohn/trade2015.rds?rlkey=5ldvbtn4550vwrbobsu5lfuhx&st=ipp306c7&dl=1"))
trade2016 <- readRDS(url("https://www.dropbox.com/scl/fi/bevq047cg7q6p96qk8rk3/trade2016.rds?rlkey=x19pybshmqf45aqclc8audnqj&st=qn68qrog&dl=1"))
trade2017 <- readRDS(url("https://www.dropbox.com/scl/fi/1a2wvu3o28ur5ce462blr/trade2017.rds?rlkey=izxqr82e8iirr9h73b48i3yfx&st=gavsra6g&dl=1"))
trade2018 <- readRDS(url("https://www.dropbox.com/scl/fi/tvqyzcgqvkfo7kxpkn9j8/trade2018.rds?rlkey=sibcdornmgwzznb5myjfaeqju&st=bnssd0n7&dl=1"))
trade2019 <- readRDS(url("https://www.dropbox.com/scl/fi/gxustrrcx6kvw9137uttd/trade2019.rds?rlkey=jjvgc0ju17465bv6e9jjnebu3&st=cpgy2cry&dl=1"))
# Take a step back and select global FTA network in 2015 for visualization
g2015 <- graph_from_adjacency_matrix(FTA[[18]]) # Plot the FTA network in year 2015
g2015_edgelist <- as_edgelist(g2015) # Convert adjacent matrix to edgelist format
# Subset country attributes in year 2015
year2015_attributes <- country_attr[country_attr$year == 2015, ]
# Calculate dyadic trade volume using the trade matrix loaded earlier
id <- list()
for(i in as.numeric(unique(rownames(trade2015)))){
id[[i]] = rep(i, 161)
exporter_id = unlist(id) # Convert list to dataframe format
}
# Create a 3 column dataframe (exporter, importer, trade_vol)
trade2015_df <- data.frame(exporter = exporter_id, importer = rep(as.numeric(unique(rownames(trade2015))), 161))
trade2015_df$trade_vol <- NA
trade2015_df <- as.data.frame(as.table(trade2015))
trade2015_df <- trade2015_df[, c(2, 1, 3)] # Reorganize columns
names(trade2015_df) <- c("exporter", "importer", "trade_vol")
# Create an igraph object for plotting
year2015_net <- graph_from_data_frame(d = g2015_edgelist, directed = TRUE,
vertices = year2015_attributes)
# Setting layout of the graph
layout <- layout.fruchterman.reingold(year2015_net)
## Warning: `layout.fruchterman.reingold()` was deprecated in igraph 2.1.0.
## ℹ Please use `layout_with_fr()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# Plotting
plot(year2015_net,
vertex.label = country_attr[,2], # Label with country abbreviation
vertex.size = 10,
vertex.label.cex = 0.5, # Node label (country abbreviation) text size
layout = layout,
edge.arrow.size = .2,
edge.arrow.width = trade2015_df[,3], # Edge width proportional to dyadic trade volume
edge.color="light gray",
vertex.frame.color = NA)
# Back to RSiena pack and continue to create dyadic variables
# varDyadCovar() means time-varying dyadic variables
# For a data array of n by n by m periods, only m-1 periods of data will be used. The last array will be discarded (you cannot use data from the m-th period to predict the network formed in the same period)
trade_Dyadvar <- varDyadCovar(array(c(trade2015, trade2016, trade2017, trade2018), dim = c(161, 161, 4)))
FTA_covar <- sienaDataCreate(FTA_networks, pop_vc, to_vc, trade_Dyadvar) # The first argument is your network, the rest are your node and edge variables
# After building the model. We first get the base terms using getEffects() function, they are the covariates whose effects are to be estimated.
siena_effects <- getEffects(FTA_covar)
# We can use includeEffects() to add additional variables to the base model. For example, do countries tend to extend FTA ties to other countries that are already tied to its immediate neighbors? This term is called "transTrip" in RSiena. We can add that to the model via includeEffects().
siena_effects <- includeEffects(siena_effects, # siena object of effects
transTrip, # Name of the term to be included
name = "FTA_networks") # Name of the dependent variable for which effects are being included
## effectName include fix test initialValue parm
## 1 transitive triplets TRUE FALSE FALSE 0 0
# Set the effect of "population" as alter, altX, meaning that do alters (other countries) tend to extend FTAs to more populous focal countries (ego)?
siena_effects <- includeEffects(siena_effects, altX,
interaction1 = "pop_vc")
## effectName include fix test initialValue parm
## 1 pop_vc alter TRUE FALSE FALSE 0 0
# Also, do countries (ego) having higher level of trade openness tend to extend FTAs to other countries (alters)?
siena_effects <- includeEffects(siena_effects, egoX,
interaction1 = "to_vc")
## effectName include fix test initialValue parm
## 1 to_vc ego TRUE FALSE FALSE 0 0
# includeEffects() function is also necessary to set up the effects of covariates from an actor-oriented perspective, that is, from the perspective of the ego to alters or the other way around.
siena_effects <- includeEffects(siena_effects, X, # X for dyadic effect, check effectsDocumentation()
interaction1 = "trade_Dyadvar")
## effectName include fix test initialValue parm
## 1 trade_Dyadvar TRUE FALSE FALSE 0 0
# Model setting
# Before we estimate our model, we need to create an object of input specifications using the sienaAlgorithmCreate() function. For pedagogical purpose, I'll set most things at their default values. We'll also set seed = 123 for replication purpose.
input_options <- sienaAlgorithmCreate(projname = "FTA_model", # Model name (you can name it whatever you like)
# maxlike = TRUE, # Whether to use maximum likelihood method or Method of Moments estimation
# nsub = 5, # Number of iterations in phase 2
# n3 = 200, # Number of iterations in phase 3
seed = 123)
## If you use this algorithm object, siena07 will create/use an output file FTA_model.txt .
# We can now estimate our model using siena07() function
FTA.mod <- siena07(x = input_options,
data = FTA_covar, # Variable list
effects = siena_effects, # Effects to be estimated (from whose perspective)
batch= TRUE,
verbose = FALSE,
returnDeps = TRUE, # Whether to return a list of simulated dependent variables (set to TRUE if you will be running sienaGOF() later)
useCluster = TRUE, # Use multiple clusters
nbrNodes = 3) # Number of processes to use if useCluster = TRUE
##
## Start phase 0
## theta: -0.11 0.00 0.00 0.00 0.00 0.00
##
## Start phase 1
## Phase 1 Iteration 1 Progress: 0%
## Phase 1 Iteration 4 Progress: 0%
## Phase 1 Iteration 10 Progress: 0%
## Phase 1 Iteration 25 Progress: 0%
## Phase 1 Iteration 40 Progress: 1%
## theta: -0.88389 -0.07301 0.01653 0.00913 0.02597 -0.00187
##
## Start phase 2.1
## Phase 2 Subphase 1 Iteration 1 Progress: 14%
## Phase 2 Subphase 1 Iteration 2 Progress: 14%
## theta -1.08375 -0.09578 0.01783 0.01205 0.02774 -0.00202
## ac 1.191 1.195 1.224 1.682 0.934 0.977
## Phase 2 Subphase 1 Iteration 3 Progress: 14%
## Phase 2 Subphase 1 Iteration 4 Progress: 14%
## theta -1.72026 -0.17148 0.02239 0.02074 0.03027 -0.00244
## ac 1.253 1.262 1.295 0.948 1.002 1.102
## Phase 2 Subphase 1 Iteration 5 Progress: 14%
## Phase 2 Subphase 1 Iteration 6 Progress: 14%
## theta -2.41235 -0.25480 0.02832 0.02848 0.02129 -0.00312
## ac 1.263 1.273 1.302 0.994 1.074 0.951
## Phase 2 Subphase 1 Iteration 7 Progress: 15%
## Phase 2 Subphase 1 Iteration 8 Progress: 15%
## theta -2.85688 -0.28992 0.03095 0.03132 0.00743 -0.00384
## ac 1.264 1.273 1.301 1.224 1.097 0.915
## Phase 2 Subphase 1 Iteration 9 Progress: 15%
## Phase 2 Subphase 1 Iteration 10 Progress: 15%
## theta -3.16447 -0.28105 0.03221 0.03270 -0.00153 -0.00538
## ac 1.264 1.273 1.301 0.872 1.097 0.740
## Phase 2 Subphase 1 Iteration 200 Progress: 23%
## theta -8.52867 -0.25979 0.03401 0.03357 -0.00562 -0.11360
## ac 1.25589 1.21618 1.25405 0.00663 0.93627 0.71015
## theta -6.07499 -0.24566 0.03204 0.03265 -0.00384 -0.06836
## ac 1.2558 1.2142 1.2498 -0.0174 0.9169 0.7007
## theta: -6.07499 -0.24566 0.03204 0.03265 -0.00384 -0.06836
##
## Start phase 2.2
## Phase 2 Subphase 2 Iteration 1 Progress: 23%
## Phase 2 Subphase 2 Iteration 2 Progress: 23%
## Phase 2 Subphase 2 Iteration 3 Progress: 23%
## Phase 2 Subphase 2 Iteration 4 Progress: 23%
## Phase 2 Subphase 2 Iteration 5 Progress: 23%
## Phase 2 Subphase 2 Iteration 6 Progress: 23%
## Phase 2 Subphase 2 Iteration 7 Progress: 23%
## Phase 2 Subphase 2 Iteration 8 Progress: 23%
## Phase 2 Subphase 2 Iteration 9 Progress: 23%
## Phase 2 Subphase 2 Iteration 10 Progress: 23%
## Phase 2 Subphase 2 Iteration 200 Progress: 31%
## theta -8.01813 -0.25968 0.03161 0.03531 -0.00399 -0.10484
## ac 0.8557 0.5867 0.6490 -0.1304 0.0155 0.5001
## theta -7.14941 -0.25226 0.03211 0.03499 -0.00477 -0.08945
## ac 0.853 0.603 0.629 -0.108 0.030 0.502
## theta: -7.14941 -0.25226 0.03211 0.03499 -0.00477 -0.08945
##
## Start phase 2.3
## Phase 2 Subphase 3 Iteration 1 Progress: 32%
## Phase 2 Subphase 3 Iteration 2 Progress: 32%
## Phase 2 Subphase 3 Iteration 3 Progress: 32%
## Phase 2 Subphase 3 Iteration 4 Progress: 32%
## Phase 2 Subphase 3 Iteration 5 Progress: 32%
## Phase 2 Subphase 3 Iteration 6 Progress: 32%
## Phase 2 Subphase 3 Iteration 7 Progress: 33%
## Phase 2 Subphase 3 Iteration 8 Progress: 33%
## Phase 2 Subphase 3 Iteration 9 Progress: 33%
## Phase 2 Subphase 3 Iteration 10 Progress: 33%
## Phase 2 Subphase 3 Iteration 200 Progress: 41%
## theta -8.14842 -0.24740 0.03297 0.03598 -0.00547 -0.10653
## ac 0.9588 0.6807 0.7299 0.1104 0.0436 0.3567
## theta -7.83950 -0.25418 0.03291 0.03512 -0.00458 -0.10128
## ac 0.9460 0.6786 0.6680 0.1003 0.0592 0.4088
## theta: -7.83950 -0.25418 0.03291 0.03512 -0.00458 -0.10128
##
## Start phase 2.4
## Phase 2 Subphase 4 Iteration 1 Progress: 43%
## Phase 2 Subphase 4 Iteration 2 Progress: 44%
## Phase 2 Subphase 4 Iteration 3 Progress: 44%
## Phase 2 Subphase 4 Iteration 4 Progress: 44%
## Phase 2 Subphase 4 Iteration 5 Progress: 44%
## Phase 2 Subphase 4 Iteration 6 Progress: 44%
## Phase 2 Subphase 4 Iteration 7 Progress: 44%
## Phase 2 Subphase 4 Iteration 8 Progress: 44%
## Phase 2 Subphase 4 Iteration 9 Progress: 44%
## Phase 2 Subphase 4 Iteration 10 Progress: 44%
## Phase 2 Subphase 4 Iteration 200 Progress: 52%
## theta -8.31718 -0.25217 0.03233 0.03451 -0.00405 -0.10981
## ac 1.0194 0.7391 0.7676 0.0564 0.1617 0.4991
## theta -8.31899 -0.25168 0.03263 0.03533 -0.00451 -0.10963
## ac 0.9752 0.6915 0.7124 0.0302 0.1586 0.5069
## theta: -8.31899 -0.25168 0.03263 0.03533 -0.00451 -0.10963
##
## Start phase 3
## Phase 3 Iteration 1 Progress 59%
## Phase 3 Iteration 301 Progress 72%
## Phase 3 Iteration 601 Progress 84%
## Phase 3 Iteration 901 Progress 96%
# Check out the results. The estimated FTA.mod object include a column of estimated coefficients and simulated standard errors
summary(FTA.mod)
## Estimates, standard errors and convergence t-ratios
##
## Estimate Standard Convergence
## Error t-ratio
##
## Rate parameters:
## 0.1 Rate parameter period 1 0.8846 ( 0.0751 )
## 0.2 Rate parameter period 2 0.0995 ( 0.0258 )
## 0.3 Rate parameter period 3 3.3593 ( 0.1444 )
## 0.4 Rate parameter period 4 0.4222 ( 0.0526 )
##
## Other parameters:
## 1. eval outdegree (density) -8.3190 ( 37.5958 ) 1.4478
## 2. eval reciprocity -0.2517 ( 0.1700 ) 0.3059
## 3. eval transitive triplets 0.0326 ( 0.0085 ) 0.6765
## 4. eval trade_Dyadvar 0.0353 ( 0.0419 ) -0.0119
## 5. eval pop_vc alter -0.0045 ( 0.0283 ) -0.0087
## 6. eval to_vc ego -0.1096 ( 0.6371 ) 0.4898
##
## Overall maximum convergence ratio: 1.6278
##
##
## Total of 2159 iteration steps.
##
## Covariance matrix of estimates (correlations below diagonal)
##
## 1413.446 4.833 0.005 -1.528 0.728 23.952
## 0.756 0.029 0.000 -0.005 0.002 0.082
## 0.017 -0.130 0.000 0.000 0.000 0.000
## -0.969 -0.728 -0.048 0.002 -0.001 -0.026
## 0.684 0.515 -0.006 -0.684 0.001 0.012
## 1.000 0.756 0.019 -0.969 0.684 0.406
##
## Derivative matrix of expected statistics X by parameters:
##
## 43.031 8.673 475.559 -97.790 1.863 -2564.529
## 4.737 170.057 668.043 62.551 8.053 69.487
## 354.378 937.051 66191.595 4420.123 -188.983 -20171.928
## -107.219 79.664 5960.394 20779.714 828.706 -438.250
## -1.226 9.990 19.606 1016.502 2454.588 -2646.250
## -2544.360 -539.067 -27643.006 7055.313 -136.653 153571.571
##
## Covariance matrix of X (correlations below diagonal):
##
## 75.656 15.212 1091.634 -118.628 12.191 -1895.675
## 0.093 351.888 3178.457 396.599 6.382 2123.378
## 0.234 0.316 288291.922 22827.959 -1991.753 120409.456
## -0.065 0.101 0.202 44097.661 1403.566 -3050.761
## 0.028 0.007 -0.073 0.132 2565.054 -6922.330
## -0.146 0.076 0.150 -0.010 -0.092 2227533.506
# It looks like transitive triplets significantly increase the probability of i-j FTA relative to with other countries, while the three dyadic and nodal attributes are not significant. In fact, their estimated coefficients are in the opposite directions.
# Estimated coefficients are reported in odds-ratio format, so they should be interpreted as exponentiated odds. For example, we see a coefficient for trade_Dyadvar of 0.0353.
# This would suggest that the odds of an FTA from i being sent to j is exp(0.0353) - 1 times higher than being sent to k, assuming that i-j FTA exists but i-k FTA does not.
# You can also see how rate parameters vary across the four periods. The rate parameter is the lowest in period 2, meaning that FTA network changes less during this period, but the rate of change kind of accelerated in period 3.
# We're now ready to plot the goodness-of-fit statistics (gof), which compares deviations between the observed and simulated networks. It will calculate gof statistics for each period
# Low p-values would indicate a potential problem. Our result looks good.
gof1 <- sienaGOF(sienaFitObject = FTA.mod,
auxiliaryFunction = IndegreeDistribution, # Returns a named vector, the distribution of the observed or simulated in-degrees for the values in levels.
verbose = TRUE, # Whether to print immediate results
join = TRUE, # Boolean: should sienaGOF test all periods individually (FALSE), or sum across periods (TRUE)
varName = "FTA_networks")
## Detected 1002 iterations and 1 group.
## Calculating auxiliary statistics for periods 1 2 3 4 .
## Period 1
## > Completed 100 calculations > Completed 200 calculations > Completed 300 calculations > Completed 400 calculations > Completed 500 calculations > Completed 600 calculations > Completed 700 calculations > Completed 800 calculations > Completed 900 calculations > Completed 1000 calculations > Completed 1002 calculations
## Period 2
## > Completed 100 calculations > Completed 200 calculations > Completed 300 calculations > Completed 400 calculations > Completed 500 calculations > Completed 600 calculations > Completed 700 calculations > Completed 800 calculations > Completed 900 calculations > Completed 1000 calculations > Completed 1002 calculations
## Period 3
## > Completed 100 calculations > Completed 200 calculations > Completed 300 calculations > Completed 400 calculations > Completed 500 calculations > Completed 600 calculations > Completed 700 calculations > Completed 800 calculations > Completed 900 calculations > Completed 1000 calculations > Completed 1002 calculations
## Period 4
## > Completed 100 calculations > Completed 200 calculations > Completed 300 calculations > Completed 400 calculations > Completed 500 calculations > Completed 600 calculations > Completed 700 calculations > Completed 800 calculations > Completed 900 calculations > Completed 1000 calculations > Completed 1002 calculations
plot(gof1)
## Calculate prediction accuracy
# Although RSiena primarily focuses on estimating parameters for network evolution models rather than direct prediction accuracy measures like classification accuracy or AUC. However, we can still assess prediction accuracy using methods based on the goodness-of-fit (GOF), which we just did, or by comparing observed versus simulated networks.
# Extract first simulated network in period 2, which is stored in $sims
# The structure of sims is a nested list: sims[[run]][[group]][[dependent variable]][[period]]. If x$maxlike=TRUE and there is only one group (like our data here) and one period, then the structure is [[run]][[dependent variable]].
sim_net <- FTA.mod$sims[[1]][1]$Data1$FTA_networks$`2` # This means first simulated network from data 1 (we only have one here) in period 2. The output is a 3-column edgelist (i, j, tie) = [node i, node j, i-j tie]
# Examine the first 10 observations
head(sim_net, 10)
## [,1] [,2] [,3]
## [1,] 1 10 1
## [2,] 1 66 1
## [3,] 1 89 1
## [4,] 1 102 1
## [5,] 1 110 1
## [6,] 2 8 1
## [7,] 2 12 1
## [8,] 2 36 1
## [9,] 2 37 1
## [10,] 2 39 1
# We now fill in edgelist values into a 161 by 161 matrix
simulated_network <- matrix(0, nrow = 161, ncol = 161)
for(i in 1:nrow(sim_net)){
simulated_network[sim_net[i,1], sim_net[i,2]] = sim_net[i,3]
}
# Extract actual FTA network observed in period 2
observed_network <- FTA_covar$depvars[[1]][, , 2]
# Compute accuracy
correct_predictions <- sum(simulated_network == observed_network) / length(observed_network)
cat("New FTAs prediction accuracy:", correct_predictions)
## New FTAs prediction accuracy: 0.9993442
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
summary(cars)
## speed dist
## Min. : 4.0 Min. : 2.00
## 1st Qu.:12.0 1st Qu.: 26.00
## Median :15.0 Median : 36.00
## Mean :15.4 Mean : 42.98
## 3rd Qu.:19.0 3rd Qu.: 56.00
## Max. :25.0 Max. :120.00
You can also embed plots, for example:
Note that the echo = FALSE
parameter was added to the
code chunk to prevent printing of the R code that generated the
plot.