Practical 3

James Hollway

Packages for plotting

There are a host of packages for plotting in R, and for plotting networks in R. Plotting in R is typically based around two main approaches: the ‘base’ approach in R by default, and the ‘grid’ approach made popular by the famous and very flexible {ggplot2} package.1 Approaches to plotting graphs or networks in R can be similarly divided. The two classic packages are {igraph} and {sna}, both building upon the base R graphics engine, but newer packages {ggnetwork} and {ggraph} build upon a grid approach.2 {migraph} builds upon the ggplot2/ggraph engine for plotting.

library(migraph)
autographr(ison_brandes)

For this exercise, we’ll use the ison_brandes dataset. This dataset is in a ‘tidygraph’ format, but migraph makes it easy to coerce this into other forms to be compatible with other packages.

ison_brandes
#> # A tbl_graph: 11 nodes and 12 edges
#> #
#> # An undirected simple graph with 1 component
#> #
#> # Node Data: 11 × 0 (active)
#> # … with 5 more rows
#> #
#> # Edge Data: 12 × 2
#>    from    to
#>   <int> <int>
#> 1     1     3
#> 2     2     3
#> 3     3     4
#> # … with 9 more rows
as_igraph(ison_brandes)
#> IGRAPH cb33d0d U--- 11 12 -- 
#> + edges from cb33d0d:
#>  [1] 1-- 3 2-- 3 3-- 4 4-- 5 4-- 6 5-- 7 6-- 7 6-- 8 7-- 9 8-- 9 9--10 9--11
as_network(ison_brandes)
#>  Network attributes:
#>   vertices = 11 
#>   directed = TRUE 
#>   hyper = FALSE 
#>   loops = FALSE 
#>   multiple = FALSE 
#>   bipartite = FALSE 
#>   total edges= 24 
#>     missing edges= 0 
#>     non-missing edges= 24 
#> 
#>  Vertex attribute names: 
#>     vertex.names 
#> 
#> No edge attributes
mat <- as_matrix(ison_brandes)

Calculating different centrality measures

Let’s start with calculating degree, as it is easy to calculate yourself. Just sum the rows or columns of the matrix!

(degrees <- rowSums(mat))
#>  [1] 1 1 3 3 2 3 3 2 4 1 1
rowSums(mat) == colSums(mat)
#>  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
# Are they all equal? Why?
# You can also just use a built in command in migraph though:
node_degree(ison_brandes)
#> [1] 0.1        0.1        0.3        0.3        0.2        0.3        + 5 others

Often we are interested in the distribution of (degree) centrality in a network. {migraph} offers a way to get a pretty good first look at this distribution, though there are more elaborate ways to do this in base and grid graphics.

plot(node_degree(ison_brandes), "h") +
  plot(node_degree(ison_brandes), "d")

Other measures of centrality can be a little trickier to calculate by hand. Fortunately, we can use functions from migraph to help:

node_betweenness(ison_brandes)
#> [1] 0.000      0.000      0.378      0.485      0.133      0.337      + 5 others
node_closeness(ison_brandes)
#> [1] 0.278      0.278      0.370      0.455      0.435      0.476      + 5 others
node_eigenvector(ison_brandes)
#> [1] 0.106      0.106      0.277      0.510      0.437      0.615      + 5 others
# TASK: Can you create degree distributions for each of these?

Note that there are an enormous number of centrality measures available in R across a range of packages. In addition to the main four used here, {igraph} includes:

graph.strength()
alpha_centrality()
power_centrality()
page_rank()
eccentricity()
hub_score()
authority_score()
subgraph_centrality()

{sna} implements most of these too, plus a few extra:

flowbet()
loadcent()
gilschmidt()
infocent()
stresscent()

There are also some dedicated centrality packages, such as centiserve, {CINNA}, {influenceR}, and {keyplayer}. There are also pretty exhaustive discussions of this online.

Plotting different centrality measures

There is also a function in {migraph} that plots our network and highlights the node with the maximum (e.g. degree) score. This is basically doing the same as what was in the original script, just gives you the function to do this:

autographr(ison_brandes, node_measure = node_degree) +
autographr(ison_brandes, node_measure = node_betweenness)

autographr(ison_brandes, node_measure = node_closeness) +
autographr(ison_brandes, node_measure = node_eigenvector)

How neat!

Calculating centralization

{migraph} also implements centralization functions. Here we are no longer interested in the level of the node, but in the level of the whole graph, so the syntax is:

graph_degree(ison_brandes)
#> [1] 0.182
graph_betweenness(ison_brandes)
#> [1] 0.318
graph_closeness(ison_brandes)
#> [1] 0.23
graph_eigenvector(ison_brandes)
#> [1] 0.484
graph_degree(ison_southern_women)
#> Mode 1 Mode 2 
#>  0.227  0.474
graph_betweenness(ison_southern_women)
#> Mode 1 Mode 2 
#> 0.0586 0.2073
graph_closeness(ison_southern_women)
#> Mode 1 Mode 2 
#>  0.284  0.442
graph_eigenvector(ison_southern_women)
#> Mode 1 Mode 2 
#> 0.0849 0.2630

By default, scores are printed to 3 decimal places, but this can be modified and, in any case, the unrounded values are retained internally and passed on. Note that for centralization in two-mode networks, two values are given (as a named vector), since normalization typically depends on the (asymmetric) number of nodes in each mode.

Exporting plots to PDF

We can print the plots we have made to PDF by point-and-click by selecting ‘Save as PDF…’ from under the ‘Export’ dropdown menu in the plots panel tab of RStudio.

If you want to do this programmatically, say because you want to record how you have saved it so that you can e.g. make some changes to the parameters at some point, this is also not too difficult.

After running the (gg-based) plot you want to save, use the command ggsave("my_filename.pdf") to save your plot as a PDF to your working directory. If you want to save it somewhere else, you will need to specify the file path (or change the working directory, but that might be more cumbersome). If you want to save it as a different filetype, replace .pdf with e.g. .png or .jpeg. See ?ggsave for more.

But what if we want to have a single image/figure with multiple plots? This can be a little tricky with gg-based plots, but fortunately the {patchwork} package is here to help.

gd <- autographr(ison_brandes, node_measure = node_degree) + 
  ggtitle("Degree", subtitle = round(graph_degree(ison_brandes), 2))
gc <- autographr(ison_brandes, node_measure = node_closeness) + 
  ggtitle("Closeness", subtitle = round(graph_closeness(ison_brandes), 2))
gb <- autographr(ison_brandes, node_measure = node_betweenness) + 
  ggtitle("Betweenness", subtitle = round(graph_betweenness(ison_brandes), 2))
ge <- autographr(ison_brandes, node_measure = node_eigenvector) + 
  ggtitle("Eigenvector", subtitle = round(graph_eigenvector(ison_brandes), 2))
library(patchwork)
(gd | gb) / (gc | ge)

# ggsave("brandes-centralities.pdf")

Tasks

  1. Import the drugnet data from Moodle (Since it is an RData file, you can just load it). load("drugnet.RData")

  2. Name a plausible research question you could ask of this data for each of the four main centrality measures (degree, betweenness, closeness, eigenvector) You may want to add these as titles or subtitles to each plot.

  3. How centralized is the network?


  1. ‘gg’ stands for the Grammar of Graphics.↩︎

  2. Others include: ‘Networkly’ for creating 2-D and 3-D interactive networks that can be rendered with plotly and can be easily integrated into shiny apps or markdown documents; ‘visNetwork’ interacts with javascript (vis.js) to make interactive networks (http://datastorm-open.github.io/visNetwork/); and ‘networkD3’ interacts with javascript (D3) to make interactive networks (https://www.r-bloggers.com/2016/10/network-visualization-part-6-d3-and-r-networkd3/).↩︎