Change Background Color of Networkd3 Plot

Change background color of networkD3 plot

Here's my hack at it. It's not pretty, but I added a function in the linkDistance argument to do the dirty work. Hopefully, someone will come along eventually with a less kludgy solution:

forceNetwork(Links = MisLinks, Nodes = MisNodes,
Source = "source", Target = "target",
Value = "value", NodeID = "name",
Group = "group", opacity = 0.8,
linkDistance =
JS('function(){d3.select("body").style("background-color", "#DAE3F9"); return 50;}'))

Another, similarly unappealing option would be to add a clickAction argument (e.g. clickAction = 'd3.select("body").style("background-color", "#DAE3F9")'), but that would only change the background if a user clicks a node.

Adjust background picture and title for plot from networkD3's forceNetwork

Here's a reproducible example that adds a title, styles the title, styles the legend text, changes the background color, and attempts to set a background image with a local file. (I can't test the background image because it depends on a number of specific factors, but it may work for you.)...

library(networkD3)
library(htmlwidgets)

subNodes <-
read.table(stringsAsFactors = FALSE, header = TRUE, text = "
nodeName nodeGroup nodeSize
Bob NorthAmerica 10
Alice NorthAmerica 10
Tom China 10
John Japan 10
")

subLinkList <-
read.table(stringsAsFactors = FALSE, header = TRUE, text = "
root children linkValue
0 1 1
0 2 1
0 3 1
")

network <- forceNetwork(Links = subLinkList, Nodes = subNodes,
Source = "root", Target = "children",
Value = "linkValue", NodeID = "nodeName",
Group = "nodeGroup",
opacity = 1, Nodesize = "nodeSize",
legend = TRUE)

network <- htmlwidgets::prependContent(network, htmltools::tags$h1("Title"))

network <- htmlwidgets::onRender(
network,
'function(el, x) {
d3.selectAll(".legend text").style("fill", "white");
d3.select("body").style("background-color", "#144370");
d3.select("h1").style("color", "red").style("font-family", "sans-serif");
d3.select("body")
.style("background-image", "url(file://C:\\Desktop\\BGP.png)")
.style("background-repeat", "no-repeat")
.style("background-position", "right bottom");
}'
)

saveNetwork(network, "~/Desktop/forceNetwork.html", selfcontained = TRUE)

changing background image within forceNetwork

You have to fully specify the URL. For instance, this seems to work...

library(networkD3)
library(htmltools)

data(MisLinks)
data(MisNodes)

browsable(
tagList(
forceNetwork(Links = MisLinks, Nodes = MisNodes,
Source = "source", Target = "target",
Value = "value", NodeID = "name",
Group = "group", opacity = 0.8),
tags$script('document.body.style.backgroundImage = "url(https://media.giphy.com/media/dgrEGTo4uk22Y/giphy.gif)"')
)
)

this is another way to do it without using htmltools...

library(networkD3)

data(MisLinks)
data(MisNodes)

linkJS <- JS('
function(){
d3.select("body")
.style("background-image", "url(https://media.giphy.com/media/dgrEGTo4uk22Y/giphy.gif)")
.style("background-repeat", "no-repeat")
.style("background-position", "right bottom");
return 50;
}')

forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
Group = "group", opacity = 0.8, linkDistance = linkJS)

Change the color of the legend text in forceNetwork for networkD3

this is a fully replicable example, using a better method to add custom JavaScript than overloading the linkDistance argument with extra code...

library(networkD3)
library(htmlwidgets)

subNodes <-
read.table(stringsAsFactors = FALSE, header = TRUE, text = "
nodeName nodeGroup nodeSize
Bob NorthAmerica 10
Alice NorthAmerica 10
Tom China 10
John Japan 10
")

subLinkList <-
read.table(stringsAsFactors = FALSE, header = TRUE, text = "
root children linkValue
0 1 1
0 2 1
0 3 1
")

colorScale <- "d3.scaleOrdinal(d3.schemeCategory20);"

fn <- forceNetwork(Links = subLinkList, Nodes = subNodes,
Source = "root", Target = "children",
Value = "linkValue", NodeID = "nodeName",
Nodesize = "nodeSize", Group = "nodeGroup",
colourScale = JS(colorScale),
charge = -500, opacity = 1, opacityNoHover = 1, fontSize = 25,
fontFamily = "Calibri", linkDistance = 200,
linkWidth = 3, linkColour = "white",
legend = TRUE, bounded = TRUE, zoom = TRUE)

htmlwidgets::onRender(
fn,
'function(el, x) {
d3.select("body").style("background-color", "#144370");
d3.selectAll(".legend text").style("fill", "white");
}'
)

forceNetwork example output

R networkD3 custom node color for radialNetwork()

OK, so I jumped the gun by posting this too early. One solution is to convert the data.tree to a data.frame and then construct a vector with a length and order that corresponds to the nodes/rows in the data.frame (as the data.frame yields a to/from/name column scheme):

tree.df <- ToDataFrameNetwork(tree, "name")
colorVector <- rep("red", nrow(tree.df))
jsarray <- paste0('["', paste(colorVector, collapse = '", "'), '"]')
nodeStrokeJS <- JS(paste0('function(d, i) { return ', jsarray, '[i]; }'))

radialNetwork(ToListExplicit(Data_tree, unname = TRUE ),
linkColour = "#ccc",
nodeColour = "#fff",
nodeStroke = nodeStrokeJS,
textColour = "#cccccc")

R networkD3 package: node coloring in simpleNetwork()

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))

Sample Image

R: networkD3 sankey plot - colours not displaying

The problem you're having must be with the data you are using, but I can't tell you precisely what because you haven't shared it. If I use properly structured data and use it as the inputs, your first, exact sankeyNetwork() command works as expected (with colors)...

(see further below for discussion of the NodeGroup parameter)

library(networkD3)

URL <- paste0('https://cdn.rawgit.com/christophergandrud/networkD3/',
'master/JSONdata/energy.json')
energy <- jsonlite::fromJSON(URL)

df_links <- energy$links
df_nodes <- energy$nodes

sankeyNetwork(Links = df_links, Nodes = df_nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
units = "Cases", fontSize = 12, nodeWidth = 20)

Sample Image

If you check the help file, the NodeGroup parameter is described as "character string specifying the node groups in the Nodes. Used to color the nodes in the network." If you're specifying NodeGroup as c(0,1,2,3,4,5,6,7), that's not a character string. That is likely why all the nodes are black using your second sankeyNetwork() command. For example, see this question about coloring groups with sankeyNetwork.

Additionally, at the top of the help file in the "Usage" section, you can see that the default value for NodeGroup is whatever is passed into NodeID. So if you do not assign anything to NodeGroup, as in your first example, then the NodeID will be used as the group... effectively creating a unique group for each node, which will be assigned a color according to the colourScale parameter.

One thing that is not explicit in the help file is that it appears that only the first word of the group name is used, so in the image above, for example, the "Oil imports", "Oil reserves", and "Oil" nodes are all considered part of the same group and therefore have the same color.



Related Topics



Leave a reply



Submit