Introduction

This R Markdown document presents an analysis of the latent space positions of countries based on arms trade data over the years. The analysis uses the latentnet package to fit a latent space model and ggplot2 to visualize the results.

Data and Preprocessing

The data used for this analysis is sourced from a cleaned dataset of arms trade registers. Below is the code to load and preprocess the data:

data <- read.csv("data/arms_data/trade-register-cleaned-year-order.csv")

Latent Space Model

The following code defines a function to fit a latent space model for a given year and generate plots. This function is applied to the data for the years 2018 to 2023.

set.seed(123)

latent_model <- function(year) {
  data_year <- subset(data, Year == year)
  data_year$Source <- as.character(data_year$Source)
  data_year$Target <- as.character(data_year$Target)
  
  nodes <- unique(c(data_year$Source, data_year$Target))
  adjacency_matrix <- matrix(0, nrow = length(nodes), ncol = length(nodes), dimnames = list(nodes, nodes))
  
  for (i in 1:nrow(data_year)) {
    source <- data_year$Source[i]
    target <- data_year$Target[i]
    weight <- data_year$Weight[i]
    adjacency_matrix[source, target] <- weight
  }
  
  net <- as.network(adjacency_matrix, directed = FALSE)
  set.edge.value(net, "weight", adjacency_matrix[adjacency_matrix != 0])
  
  data.fit <- ergmm(net ~ edges + euclidean(d = 2, G=3), verbose = TRUE)
  summary(data.fit)
  
  latent_positions <- data.fit$mcmc.mle$Z
  latent_positions_df <- data.frame(
    Country = nodes,
    X = latent_positions[, 1],
    Y = latent_positions[, 2]
  )
  
  p <- ggplot() +
    geom_point(data = latent_positions_df, aes(x = X, y = Y), color = "blue") +
    geom_text(data = latent_positions_df, aes(x = X, y = Y, label = Country), vjust = -0.5, hjust = 0.5) +
    ggtitle(paste("Latent Positions of Countries for Year", year)) +
    xlab("Latent Dimension 1") +
    ylab("Latent Dimension 2") +
    theme_minimal()
  
  print(p)  
}

years <- c(2018, 2019, 2020, 2021, 2022, 2023)
for (year in years) {
  latent_model(year)
}
## Generating initial values for MCMC:
## Computing geodesic distances... Finished.
## Computing MDS locations... Finished.
## Computing other initial values... Finished.
## Finding the conditional posterior mode... Finished.
## Burning in... Finished.
## Starting sampling run... Finished.
## Post-processing the MCMC output:
## Performing label-switching... Finished.
## Fitting the MKL locations... Finished.
## Fitting MBC conditional on MKL locations... Finished.
## Performing Procrustes transformation... Finished.
## Warning in eval(substitute(expr), data, enclos = parent.frame()): Bad
## clustering: treating 2 clusters as empty.
## NOTE: It is not certain whether it is appropriate to use latentnet's BIC to select latent space dimension, whether or not to include actor-specific random effects, and to compare clustered models with the unclustered model.

## Generating initial values for MCMC:
## Computing geodesic distances... Finished.
## Computing MDS locations... Finished.
## Computing other initial values... Finished.
## Finding the conditional posterior mode... Finished.
## Burning in... Finished.
## Starting sampling run... Finished.
## Post-processing the MCMC output:
## Performing label-switching... Finished.
## Fitting the MKL locations... Finished.
## Fitting MBC conditional on MKL locations... Finished.
## Performing Procrustes transformation... Finished.
## Generating initial values for MCMC:
## Computing geodesic distances... Finished.
## Computing MDS locations... Finished.
## Computing other initial values... Finished.
## Finding the conditional posterior mode... Finished.
## Burning in... Finished.
## Starting sampling run... Finished.
## Post-processing the MCMC output:
## Performing label-switching... Finished.
## Fitting the MKL locations... Finished.
## Fitting MBC conditional on MKL locations... Finished.
## Performing Procrustes transformation... Finished.
## Warning in eval(substitute(expr), data, enclos = parent.frame()): Bad
## clustering: treating 2 clusters as empty.

## Generating initial values for MCMC:
## Computing geodesic distances... Finished.
## Computing MDS locations... Finished.
## Computing other initial values... Finished.
## Finding the conditional posterior mode... Finished.
## Burning in... Finished.
## Starting sampling run... Finished.
## Post-processing the MCMC output:
## Performing label-switching... Finished.
## Fitting the MKL locations... Finished.
## Fitting MBC conditional on MKL locations... Finished.
## Performing Procrustes transformation... Finished.
## Warning in eval(substitute(expr), data, enclos = parent.frame()): Bad
## clustering: treating 2 clusters as empty.

## Generating initial values for MCMC:
## Computing geodesic distances... Finished.
## Computing MDS locations... Finished.
## Computing other initial values... Finished.
## Finding the conditional posterior mode... Finished.
## Burning in... Finished.
## Starting sampling run... Finished.
## Post-processing the MCMC output:
## Performing label-switching... Finished.
## Fitting the MKL locations... Finished.
## Fitting MBC conditional on MKL locations... Finished.
## Performing Procrustes transformation... Finished.
## Generating initial values for MCMC:
## Computing geodesic distances... Finished.
## Computing MDS locations... Finished.
## Computing other initial values... Finished.
## Finding the conditional posterior mode... Finished.
## Burning in... Backing off: too few acceptances. If you see this message several times in a row, use a longer burnin.
## Finished.
## Starting sampling run... Finished.
## Post-processing the MCMC output:
## Performing label-switching... Finished.
## Fitting the MKL locations... Finished.
## Fitting MBC conditional on MKL locations... Finished.
## Performing Procrustes transformation... Finished.
## Warning in eval(substitute(expr), data, enclos = parent.frame()): Bad
## clustering: treating 2 clusters as empty.

Including Pre-generated Plots

Conclusion

This analysis provides a visual representation of the latent space positions of countries based on arms trade data over several years. The latentnet and ggplot2 packages in R are powerful tools for such network analyses and visualizations.

Rplot2019 Rplot2020 Rplot2021 Rplot2022 Rplot2023