The new grapjhs
function makes it easy to plot interactive 3-d graph objects from the igraph package.
This vignette explores basic use of the graphjs
function using the LeMis
data included in the threejs
package. The LeMis
data contain character coappearance data for Victor Hugo’s novel Les Misérables, compiled in the Stanford Graph Database by Donaled Knuth (see http://www-cs-faculty.stanford.edu/~uno/sgb.html) and taken from the D3.js force directed graph example by Mike Bostock (http://bl.ocks.org/mbostock/4062045).
We explore the graphjs
function by looking at the graph of character coappearance in Les Misérables. We then illustrate a few measures of network centrality and connectivity.
Plots produced by graphjs
are primarily designed for mouse interaction. They do also try to support touch interfaces with touch analogs of the indicated mouse operations.
brush=TRUE
argument to highlight clicked vertices.An attempt is made to support touch equivalents to the mouse operations, but touch interfaces will likely not work as well as a traditional mouse or trackpad set up.
Also see the vignette on crosstalk interaction here: https://bwlewis.github.io/rthreejs/crosstalk.html .
Let’s plot a force directed graph of the characters in Les Misérables. Each circle in the plot represents a character and an edge between circles indicates that the corresponding characters interacted in the novel. The colors are taken from http://bl.ocks.org/mbostock/4062045.
suppressPackageStartupMessages(library(threejs, quietly=TRUE))
data(LeMis)
graphjs(LeMis, vertex.size = 1)
Perhaps most intuitive measure of graph centrality, degree centrality of a node simply counts the number of other nodes it’s connected to.
The following example computes degree centrality and adjusts the sizes of the nodes accordingly. Bigger nodes are connected to more nodes than smaller ones.
M = as_adjacency_matrix(LeMis)
v = Matrix::colSums(M)
v = v / max(v) # normalize
graphjs(LeMis, vertex.size = 3 * v)
One possibile criticism of degree centrality is that it does not take into account how “important” the nodes connected to a given node are. Eigen centrality helps to account for that by, loosely, recursively measuring degree centrality—that is, nodes connected to other nodes that themselves are highly connected receive more weight.
Eigen centrality is defined by the entries of the eigenvector of the adjacency matrix associated with the largest eigenvalue. We can say “largest” eigenvalue because our adjacency matrix is symmetric, and therefore its eigenvalues are real numbers. The fact that there is a single, non-degenerate largest eigenvalue is a consequence of the Perron-Frobenius theorem, one of the most beautiful results in linear algebra.
The next example adjusts the sizes of the nodes by eigen centrality.
v = abs(eigen(M)$vector[,1])
v = v / max(v)
graphjs(LeMis, vertex.size = 3 * v)
Eigen centrality gives more weight to nodes that are connected to other nodes with lots of connections. Other measures like f-subgraph centrality (see, for example, E. Estrada and D. J. Higham, Network properties revealed through matrix functions, SIAM Rev., 52 (2010), pp. 696–714.) adjust this concept to emphasize shorter paths more than longer ones. Roughly, nodes that are connected to lots of other nodes by relatively short paths recieve more weight in this measure of graph centrality.
The next example illustrates f-subgraph centrality for the exponential function f(x)=exp(x) using the matrix exponential function expm
from R’s Matrix package.
library(Matrix)
v = diag(expm(M))
v = v / max(v)
graphjs(LeMis, vertex.size = 3 * v)