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");
}'
)
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))
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)
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
Iteratively Constructed Dataframe in R
Order Categorical Data in a Stacked Bar Plot with Ggplot2
Ggplot2 Add a Legend for Several Stat_Functions
Fast Way to Group Variables Based on Direct and Indirect Similarities in Multiple Columns
Boxplot of Table Using Ggplot2
How to Create a Line Plot with Groups in Base R Without Loops
Draw Multiple Squares with Ggplot
R: Replacing Foreign Characters in a String
Ggplot2: How to Transparently Shade Alternate Days on a Plot
How Does R's Ifelse Work with Character Data
Ggplot2': Label Values of Barplot That Uses 'Fun.Y="Mean"' of 'Stat_Summary'
R, Sweave, Latex - Escape Variables to Be Printed in Latex
Group_By() into Fill() Not Working as Expected
R Output Without [1], How to Nicely Format
How to Access Browser Session/Cookies from Within Shiny App
Retain Attributes When Using Gather from Tidyr (Attributes Are Not Identical)