Interactive and Dynamic Social Network Visualization in R

Prof James P. Curley
6th April 2016

Section II - Interactive Graphs

Some Interactive Options


  • networkD3 (d3.js)
  • threejs (d3.js)
  • visNetwork (vis.js)
  • ndtv (statnet/NetworkDynamic)

Quick note


There may be some performance issues if reading this in the browser.

This is due to the multiple iframes I've used for the talk - any slow loading is my fault and not related to the packages

Please refresh your browser at any slide that is slow to load

networkD3


D3.js force network graphs via a htmlwidget

http://christophergandrud.github.io/networkD3/

authors: Christopher Gandrud, JJ Allaire, & Kent Russell


Click and drag a node!

networkD3 - simpleNetwork()


# adapted from vignette

src <- c("A", "I", "A", "B",
         "B", "E", "C", "C", 
         "D", "C", "B")

target <- c("B", "C", "F", "J",
            "H", "F", "G", "H", 
            "I", "I", "I")

networkData <- data.frame(src, target)

# Plot
simpleNetwork(networkData, 
              nodeColour = "red", 
              nodeClickColour="blue",
              zoom=T,
              height=300,
              width=300, 
              fontSize = 16)

networkD3 forceNetwork()

networkD3 forceNetwork()


library(networkD3)
library(randomNames) 
library(igraph)

# Basic Graph
df <- random_name_df(seed=221)
g <- graph.data.frame(df, directed=F) # raw graph


## Make a vertices df
vertices<-data.frame(
name = V(g)$name,
group = edge.betweenness.community(g)$membership,
betweenness = (betweenness(g,directed=F,normalized=T)*115)+0.1 #so size isn't tiny
) 
#nb. can also adjust nodesize with `radiusCalculation`

# create indices (indexing needs to be JS format)
df$source.index = match(df$source, vertices$name)-1
df$target.index = match(df$target, vertices$name)-1
head(df)

networkD3 forceNetwork()


# supply a edgelist + nodelist
d3 = forceNetwork(Links = df, Nodes = vertices,
                  Source = 'source.index', Target = 'target.index',
                  NodeID = 'name',
                  Group = 'group', # color nodes by group calculated earlier
                  charge = -50, # node repulsion
                  linkDistance = 20,
                  zoom = T, 
                  opacity = 1,
                  fontSize=24)

show(d3)


networkD3 forceNetwork()


### Now add node size by betweenness
d3 = forceNetwork(Links = df, Nodes = vertices,
                  Source = 'source.index', Target = 'target.index',
                  NodeID = 'name',
                  Nodesize = 'betweenness', #sizing nodes by centrality
                  Group = 'group', # color nodes by group calculated earlier
                  charge = -50, # node repulsion
                  linkDistance = 20,
                  zoom = T, 
                  opacity = 1,
                  fontSize=24)

show(d3)


networkD3 forceNetwork()


## The "JS" function allows you to directly write javascript

### Adding a colorScale

library(RColorBrewer)

scalecolors <- function(nodes, palette) {
  n <- max(unique(vertices$group))
  cols <- rev(RColorBrewer::brewer.pal(n, palette))
  cols <- paste0("'", paste(cols, collapse = "', '"), "'")
  networkD3::JS(paste0('d3.scale.ordinal().domain([0,', n, ']).range([', cols, '])'))
}

scalecolors(vertices, 'YlOrRd')

#"d3.scale.ordinal().domain([0,9]).range(['#FFFFCC', '#FFEDA0', '#FED976', '#FEB24C', '#FD8D3C', '#FC4E2A', '#E31A1C', '#BD0026', '#800026'])"

networkD3 forceNetwork()


#Yellow-Orange-Red
d3 = forceNetwork(Links = df, Nodes = vertices,
                  Source = 'source.index', Target = 'target.index',
                  NodeID = 'name',
                  Group = 'group', 
                  Nodesize = 'betweenness',
                  colourScale = scalecolors(vertices, 'YlOrRd'),
                  charge = -70, # node repulsion
                  linkDistance = 25,
                  zoom = T, 
                  opacity = 1,
                  fontSize=24)

show(d3)


networkD3 forceNetwork()


### Change Background Color and Edge Color

library(htmltools)
browsable(
  tagList(
    forceNetwork(Links = df, Nodes = vertices,
                 Source = 'source.index', Target = 'target.index',
                 NodeID = 'name',
                 Group = 'group', 
                 Nodesize = 'betweenness',
                 colourScale = scalecolors(vertices, 'YlOrRd'),
                 linkColour = "#fff",
                 charge = -80, # node repulsion
                 linkDistance = 25,
                 zoom = T, 
                 opacity = 1,
                 fontSize=24),
    tags$script(
      '
      document.body.style.backgroundColor = "#000000"
      '      
    )
  )
)
#There is also a naughty way of changing background color - see the gist for more info


networkD3 forceNetwork()


# standard effect adapted from vignette:

data(MisLinks)
data(MisNodes)

# Create graph
forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source",
             Target = "target", Value = "value", NodeID = "name",
             Group = "group", opacity = 1, zoom = F, bounded = T)

# with a simple click action - make the circles bigger when clicked
MyClickScript <- 
  ' d3.select(this).select("circle")
.transition().duration(750).attr("r", 40)
'


forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source",
             Target = "target", Value = "value", NodeID = "name",
             Group = "group", opacity = 1, zoom = T, fontSize=24,
             clickAction = MyClickScript)



thanks to Kent Russell

Columbia Friendship & Study Networks


I've been working with Kaytee Turetsky and Prof Valerie Purdie-Vaughns from Columbia University's Laboratory of Social Relations and the Social Mind following students over the course of their semesters, examining how friendship and study networks change over time.


The next networkD3 graph shows the friendship network of an intro-Bio course, with color gradient (light green to dark green) representing the betweenness of nodes.

live version: http://curleylab.psych.columbia.edu/friendship1.html


Friendship Network:
Columbia Intro Bio



The final two graphs show the college affiliation (Barnard College, Columbia College, General Studies) of students in an intro-Cultural Psych class at the beginning (t1) and end (t2) of semester.


t1


t2