Notes for November 13th/15th: Networks

Contents

Network data in ggplot

First let’s set up some libraries.

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.2.1     ✔ purrr   0.3.3
## ✔ tibble  2.1.3     ✔ dplyr   0.8.3
## ✔ tidyr   1.0.0     ✔ stringr 1.4.0
## ✔ readr   1.3.1     ✔ forcats 0.4.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter()  masks stats::filter()
## ✖ purrr::is_null() masks testthat::is_null()
## ✖ dplyr::lag()     masks stats::lag()
## ✖ dplyr::matches() masks tidyr::matches(), testthat::matches()
library(socviz)
## 
## Attaching package: 'socviz'
## The following object is masked from 'package:kjhutils':
## 
##     %nin%
## Install if necessary with install.packages()
library(ggraph)
library(tidygraph)
## 
## Attaching package: 'tidygraph'
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:testthat':
## 
##     matches
library(graphlayouts)

Next, load the data package. If you don’t have the kjhnet package installed, then use drat to tell R where to find it adn then install.packages()

# drat::addRepo("kjhealy")
# install.packages("kjhnet")

library(kjhnet)

Paul Revere

First the groups data:

revere_groups
## # A tbl_graph: 7 nodes and 49 edges
## #
## # An undirected multigraph with 1 component
## #
## # Node Data: 7 x 2 (active)
##      id name            
##   <int> <chr>           
## 1     1 st_andrews_lodge
## 2     2 loyal_nine      
## 3     3 north_caucus    
## 4     4 long_room_club  
## 5     5 tea_party       
## 6     6 boston_committee
## # … with 1 more row
## #
## # Edge Data: 49 x 3
##    from    to value
##   <int> <int> <dbl>
## 1     1     1    53
## 2     1     2     2
## 3     1     3     3
## # … with 46 more rows

We’ll calculate a centrality measure (that we might look at separately) and then plot the edges weighted by the number of ties between organzations.

revere_groups %>%
  mutate(centrality = centrality_degree()) %>%
  ggraph(layout = "kk") +
  geom_edge_link(aes(width = value), color = "gray80") +
  geom_node_label(aes(label = name))

Next, the persons data:

revere_persons
## # A tbl_graph: 254 nodes and 19666 edges
## #
## # An undirected multigraph with 1 component
## #
## # Node Data: 254 x 2 (active)
##      id name              
##   <int> <chr>             
## 1     1 John_Adams        
## 2     2 Samuel_Adams      
## 3     3 Dr_Allen          
## 4     4 Nathaniel_Appleton
## 5     5 Gilbert_Ash       
## 6     6 Benjamin_Austin   
## # … with 248 more rows
## #
## # Edge Data: 19,666 x 3
##    from    to value
##   <int> <int> <dbl>
## 1     1     1     2
## 2     1     2     2
## 3     1     3     1
## # … with 1.966e+04 more rows
revere_persons %>%
  activate(nodes) %>%
  mutate(centrality = centrality_eigen()) %>%
  ggraph(layout = "stress") +
  geom_edge_link0(aes(filter = value > 1, width = value), color = "gray90") +
  geom_node_point() +
  geom_node_label(aes(filter = centrality > 0.9, label = name), size = rel(2.5))

The Iliad Data

These data are from Rossman (2017), see https://osf.io/jasf4/ for details.

il_tidy
## # A tbl_graph: 311 nodes and 292 edges
## #
## # A directed multigraph with 23 components
## #
## # Node Data: 311 x 3 (active)
##      id name            affil
##   <int> <chr>           <chr>
## 1     1 Antilochus      A    
## 2     2 Agenor          T    
## 3     3 Telamonian Ajax A    
## 4     4 Antiphus        T    
## 5     5 Odysseus        A    
## 6     6 Peirous         T    
## # … with 305 more rows
## #
## # Edge Data: 292 x 3
##    from    to act  
##   <int> <int> <chr>
## 1     1    41 kills
## 2     2    42 kills
## 3     3    43 kills
## # … with 289 more rows

Here’s the overall network.

il_tidy %>%
  activate(nodes) %>%
  ggraph(layout = "fr") +
  geom_edge_link(color = "gray80") +
  geom_node_point(aes(color = affil)) +
  scale_color_manual(values = c("blue", "red"), labels = c("Athenian", "Trojan")) +
  guides(color = guide_legend(title = "Side", )) +
  labs(title = "Killings in The Iliad") +
  theme(plot.title = element_text(size = rel(3)))

Calculate and plot the Betweenness Centrality of the male characters.

il_tidy %>%
  activate(nodes) %>%
  mutate(centrality = centrality_degree(),
         betweenness = centrality_betweenness()) %>%
  arrange(desc(betweenness)) %>%
  top_n(10, wt = betweenness) %>%
  ggplot(mapping = aes(x = betweenness, y = reorder(name, betweenness), color = affil)) + 
  geom_point(size = 3) + 
  labs(x = "Betweenness", y = NULL, color = "Side") +
  theme_minimal() + 
  theme(legend.position = "top")

And the “Google centrality” (i.e., Pagerank) of the male characters. Notice that we calculate this on the edges, not the nodes.

il_tidy %>%
  activate(edges) %>%
  filter(act == "kills") %>%
  reroute(from = to, to = from) %>%
  activate(nodes) %>%
  mutate(p_rank = centrality_pagerank()) %>%
  top_n(10, wt = p_rank) %>%
  ggplot(mapping = aes(x = p_rank,
                       y = reorder(name, p_rank),
                       color = affil)) +
  geom_point(size = 3) +
    labs(x = "PageRank Centrality", y = NULL,
         color = "Side") +
  theme_minimal() +
  theme(legend.position = "top")

Finally a graph with labels. You may need to install the prismatic library here.

label_colors <- c(prismatic::clr_lighten("blue", 0.7), 
                  prismatic::clr_lighten("red", 0.7))
il_tidy %>%
  activate(nodes) %>%
  mutate(centrality = centrality_degree(mode = "out")) %>%
  ggraph(layout = 'graphopt') +
  geom_edge_link(aes(start_cap = label_rect(node1.name),
                     end_cap = label_rect(node2.name)),
                 arrow = arrow(length = unit(1.5, 'mm'))) +
  geom_node_point(aes(color = affil)) +
  scale_color_manual(values = c("blue", "red"), labels = c("Athenian", "Trojan")) +
  guides(color = FALSE, fill = FALSE) +
  geom_node_label(aes(filter = centrality > 3, label = name, fill = affil), size = rel(2.5)) +
  scale_fill_manual(values = label_colors) + 
  labs(title = "Killings in The Iliad") +
  theme(plot.title = element_text(size = rel(3)))