0

Consider the following network, can nodes be bordered with colors based on a column from the MisNodes data frame using the forceNetwork function in . It has an option to color the edges but not the node borders.

library(networkD3) 

# Load data
data(MisLinks)
data(MisNodes)

# Plot
forceNetwork(Links = MisLinks, Nodes = MisNodes,
            Source = "source", Target = "target",
            Value = "value", NodeID = "name",
            Group = "group", opacity = 0.8)
CJ Yetman
  • 8,373
  • 2
  • 24
  • 56
Wasim Aftab
  • 638
  • 1
  • 8
  • 16

1 Answers1

1

Assuming your nodes data frame has a column with valid color values in it, you can prepend custom JavaScript to set the node border colors with it...

library(networkD3)
library(htmlwidgets)

# Load data
data(MisLinks)
data(MisNodes)

MisNodes$border <- c(rep("#F00", 20), rep("#0F0", 20), rep("#00F", 20), rep("#F00", 17))


# Plot
fn <- forceNetwork(Links = MisLinks, Nodes = MisNodes,
             Source = "source", Target = "target",
             Value = "value", NodeID = "name",
             Group = "group", opacity = 0.8)


# add the color column back in to the data in the htmlwidget because
# forceNetwork only passes through the necessary columns
fn$x$nodes$border <- MisNodes$border


# add custom JavaScript to set the node stroke to the color in the border column
fn <- htmlwidgets::onRender(fn, 
  'function(el, x) { d3.selectAll("circle").style("stroke", d => d.border); }')


# display
fn

enter image description here

CJ Yetman
  • 8,373
  • 2
  • 24
  • 56
  • Thanks for your time. I have solved it slightly differently. I have forked your package and provided an optional argument to forceNetwork(), (where user can provide colors either as a column from the MisNodes df or a single color code for all the nodes) and also made changes to corresponding js file. However, it worked this way coloring node borders but when I tried to use same approach for filling node with colors, it did not work. In that case I had to use colourScale argument colourScale = JS('d3.scaleOrdinal().domain(["g1", "g2", "g3"]).range(["#666", "#F3C", "#FF3"]);'). – Wasim Aftab Feb 23 '20 at 15:46