Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R networkD3 package: node coloring in simpleNetwork()

The networkD3 package (see here and here) allows a user to create simple interactive networks:

# Load package
library(networkD3)

# Create fake data
src <- c("A", "A", "A", "A",
        "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J",
            "E", "F", "G", "H", "I")
networkData <- data.frame(src, target)

# Plot
simpleNetwork(networkData)

Is there a way to specify that I want all elements in the src vector to be a certain color, while allowing all the elements in the target vector to be a different color? This would allow me to visually distinguish src nodes from target nodes in the network.

This functionality doesn't seem to be currently supported in simpleNetwork() (but I'm hoping somebody could help me out with a homebrew script):

enter image description here

A similar but not related question was asked here.

like image 228
warship Avatar asked Feb 08 '16 22:02

warship


People also ask

How can I see the network created in R?

To see the network we created, we just need to type its name: Since we allowed the zoom option, double click on any node will zoom in the network and allow us to see that node and its neighborhood in more details: and use it independently from R: click here to see the network exported as html file.

How to zoom in the network in R?

Since we allowed the zoom option, double click on any node will zoom in the network and allow us to see that node and its neighborhood in more details: and use it independently from R: click here to see the network exported as html file.

How to color nodes based on their degree in a group?

Hence, if we want all nodes to be colored differently, each node will be assigned to different group (one can use node ID as a group number). In our case, we colored nodes based on their degree (“ nodeDegree “) – all nodes with the same degree will be colored the same color.

Is it possible to visualize network with networkd3?

The simplicity to visualize network with networkD3 may be enough to make one ignore the lack of some features that would be available when working directly with D3, but would require significant time spent in learning D3 and designing a custom network visualization. Finally, here is the code used to create the network:


2 Answers

Here's how to control colour of nodes with forceNetwork. Notice this still won't tell you the direction of the links because some nodes are source for some links and target for others - so you'll need to rethink that logic somehow. But anyway, here's controlling colour of nodes.

# Load package
library(networkD3)
library(dplyr) # to make the joins easier

# Create fake data
src <- c("A", "A", "A", "A",
         "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J",
            "E", "F", "G", "H", "I")
networkData <- data.frame(src, target, stringsAsFactors = FALSE)

nodes <- data.frame(name = unique(c(src, target)), stringsAsFactors = FALSE)
nodes$id <- 0:(nrow(nodes) - 1)


# create a data frame of the edges that uses id 0:9 instead of their names
edges <- networkData %>%
   left_join(nodes, by = c("src" = "name")) %>%
   select(-src) %>%
   rename(source = id) %>%
   left_join(nodes, by = c("target" = "name")) %>%
   select(-target) %>%
   rename(target = id)

edges$width <- 1

# make a grouping variable that will match to colours
nodes$group <- ifelse(nodes$name %in% src, "lions", "tigers")

# simple with default colours
forceNetwork(Links = edges, Nodes = nodes, 
             Source = "source",
             Target = "target",
             NodeID ="name",
             Group = "group",
             Value = "width",
             opacity = 0.9,
             zoom = TRUE)

# control colours with a JS ordinal scale
# edited 20 May 2017 with updated code from Renal Chesak's answer:
ColourScale <- 'd3.scaleOrdinal()
            .domain(["lions", "tigers"])
           .range(["#FF6900", "#694489"]);'

forceNetwork(Links = edges, Nodes = nodes, 
             Source = "source",
             Target = "target",
             NodeID ="name",
             Group = "group",
             Value = "width",
             opacity = 0.9,
             zoom = TRUE,
             colourScale = JS(ColourScale))

enter image description here

like image 101
Peter Ellis Avatar answered Oct 10 '22 01:10

Peter Ellis


Peter Ellis' answer does the job, but this is an alternate approach, which imho is bit more concise and easier to understand...

(Also, it should be noted that nodes can be in both the source and the target vectors at the same time, in which case, which color they should be, given your specification, is uncertain.)

library(networkD3)

src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
networkData <- data.frame(src, target, stringsAsFactors = FALSE)

# make a nodes data frame out of all unique nodes in networkData
nodes <- data.frame(name = unique(c(networkData$src, networkData$target)))

# make a group variable where nodes in networkData$src are identified
nodes$group <- nodes$name %in% networkData$src

# make a links data frame using the indexes (0-based) of nodes in 'nodes'
links <- data.frame(source = match(networkData$src, nodes$name) - 1,
                    target = match(networkData$target, nodes$name) - 1)

forceNetwork(Links = links, Nodes = nodes, Source = "source",
             Target = "target", NodeID ="name", Group = "group",
             opacity = 1, opacityNoHover = 1)

enter image description here

like image 22
CJ Yetman Avatar answered Oct 10 '22 01:10

CJ Yetman