Week 42 | adjacency matrix

This Week’s Widget - adjacency matrix

This beautiful little adjacency matrix by Mike Bostock inspired this Github issue/request. At the beginning of the week, I started banging away on a htmlwidget extension to networkD3 using Elijah Meeks’ d3.layout.adjacencyMatrix. The deeper I got the more I realized that an adjacency matrix really is just a subset of a heatmap, so then I started replicating Matthew Lincoln’s fine Shiny/ggplot2 adjacency matrix with RStudio/Joe Cheng’s d3heatmap. This bl.ock visualizing 2015 NCAA football is one result.

As the end of this week nears, I don’t have a whole lot in terms of a finished htmlwidget, but I do have some prototype code and some examples.

Installation

This is not on CRAN and not even in the master branch, so to install we will need some help from devtools::install_github.

devtools::install_github("timelyportfolio/networkD3@feature/adjacency")

For d3heatmap, you can just install.packages("d3heatmap").

Examples

Let’s start small with the bridges of Koenigsberg.

#devtools::install_github("timelyportfolio/networkD3@feature/adjacency")

library(networkD3)
library(igraph)

data(Koenigsberg, package="igraphdata")
koen_df <- get.data.frame(upgrade_graph(Koenigsberg), what="both")
koen_df$edges$from <- match(koen_df$edges$from,koen_df$vertices$name) - 1
koen_df$edges$to <- match(koen_df$edges$to,koen_df$vertices$name) - 1

adjacencyNetwork(
  Links = koen_df$edges,
  Nodes = koen_df$vertices,
  Source = "from",
  Target = "to",
  NodeID = "name",
  Group = "name",
  margin = list(left=150, top=150),
  colourScale = htmlwidgets::JS("d3.scale.category10()"),
  width = 500,
  height = 500
)

Now we can compare with d3heatmap.

library(d3heatmap)

d3heatmap(
  get.adjacency(
    upgrade_graph(Koenigsberg),
    sparse = FALSE
  ),
  colors = "Blues",
  dendrogram = "none",
  cexRow = 0.7, cexCol = 0.7
)

One more example with the karate data from igraphdata.

library(networkD3)
library(igraph)

data(karate, package="igraphdata")
karate_df <- get.data.frame(upgrade_graph(karate), what="both")
karate_df$edges$from <- match(karate_df$edges$from,karate_df$vertices$name) - 1
karate_df$edges$to <- match(karate_df$edges$to,karate_df$vertices$name) - 1

adjacencyNetwork(
  Links = karate_df$edges,
  Nodes = karate_df$vertices,
  Source = "from",
  Target = "to",
  NodeID = "name",
  Group = "Faction",
  margin = list(left=150, top=150),
  width = 500,
  height = 500
)

Again, let’s do the same network but in d3heatmap, but we will include the dendrogram this time.

library(d3heatmap)

d3heatmap(
  get.adjacency(
    upgrade_graph(karate),
    sparse = FALSE
  ),
  colors = "Blues",
  cexRow = 0.7, cexCol = 0.7
)

With a little sorting, our karate adjacency matrix can be more helpful.

# community then by degree sorting
library(dplyr)
fc <- fastgreedy.community(karate)
karate_df <- get.data.frame(karate, what = "both")
karate_df$vertices <- data.frame(membership = unclass(membership(fc)), degree = degree(karate)) %>%
  mutate( name = rownames(.) ) %>%
  arrange( membership, desc( degree ) ) %>%
  select( name ) %>%
  as.vector %>%
  inner_join( karate_df$vertices )
karate_df$edges$from <- match(karate_df$edges$from,karate_df$vertices$name) - 1
karate_df$edges$to <- match(karate_df$edges$to,karate_df$vertices$name) - 1

adjacencyNetwork(
  Links = karate_df$edges,
  Nodes = karate_df$vertices[,c(2,1)],
  Source = "from",
  Target = "to",
  NodeID = "name",
  Group = "Faction",
  margin = list(left=100, top=100)
)

As you can see, I have a long way to go with this. The dynamic sorting in the Mike Bostock example is probably first to implement. I’d love help, comments, feedback, anything…

Thanks

Thanks Mike Bostock for d3 and another great example using it. Thanks Elijah Meeks for all his d3 posts, book, examples, and layouts. Thanks Joe Cheng for d3heatmap.

As always, thanks to

  • Ramnath Vaidyanathan and RStudio for htmlwidgets
  • all the contributors to R and JavaScript