Search code examples
rd3.jsnetworkd3

Custom Colors for networkD3 sankeyGraph()


Important clarification: I am using an older, non-CRAN branch of networkD3 forked by Florian Breitwieser fbreitwieser/networkD3/tree/add_zoom. Florian's branch added zooming capabilities to Sankey graphs, but was not merged into the CRAN package. Since that particular branch has not been updated since 2016, the syntax here differs than what should be used with the current (as of 2018-02-15) CRAN release.


I am attempting to apply custom colors to a networkD3 sankeyGraph().

I am attempting to reproduce Example #1 from https://www.r-graph-gallery.com/322-custom-colours-in-sankey-diagram/ .

I'm guessing there may have been a package update or two since that example was originally posted, any ideas on what might need to change here?

(Almost verbatim) Code From Example

(The only non-formatting change I made was to load magrittr directly instead of piling on a dozen tidyverse packages just for the pipe)

# Library
library(networkD3)
#library(tidyverse)
library(magrittr)

# Make a connection data frame
links=data.frame(source=c("group_A","group_A", "group_B", "group_C", "group_C", "group_E"),
                 target=c("group_C","group_D", "group_E", "group_F", "group_G", "group_H"),
                 value=c(2,3, 2, 3, 1, 3))

# From these flows we need to create a node data frame: it lists every entities involved in the flow
nodes=data.frame(name=c(as.character(links$source), as.character(links$target)) %>% unique())
links$IDsource=match(links$source, nodes$name)-1 
links$IDtarget=match(links$target, nodes$name)-1

# prepare color scale: I give one specific color for each node.
my_color <- 'd3.scaleOrdinal() .domain(["group_A", "group_B","group_C", "group_D", "group_E", "group_F", "group_G", "group_H"]) .range(["blue", "blue" , "blue", "red", "red", "yellow", "purple", "purple"])'

# Make the Network. I call my colour scale with the colourScale argument
sankeyNetwork(Links = links,
              Nodes = nodes,
              Source = "IDsource",
              Target = "IDtarget",
              Value = "value",
              colourScale= my_color,
              NodeID = "name")

What was supposed to come out:

desired output

What I get out:

Current Output

Commenting out colourScale shows everything else is working.

sankeyNetwork(Links = links,
              Nodes = nodes,
              Source = "IDsource",
              Target = "IDtarget",
              Value = "value",
              # colourScale= my_color,
              NodeID = "name")

partial

Some things I tried:

The Q&A Modify networkD3 sankey plot with user-defined colors seemed promising, but when I run what was marked as an accepted answer I get a blank output again.

How to color groups in networkD3's sankeyNetwork? also seemed very promising since it had an answer from a package contributor(@cjyetman), and while I was able to reproduce his minimal example, I was unsuccessful in adding a custom color mapping.

Own colour range for Sankey Diagram with networkD3 package in R yet again seemed to cover what the appropriate syntax would be, but I struck out again on applying the advice there to this problem.


Solution

  • Important clarification: I am using an older, non-CRAN branch of networkD3 forked by Florian Breitwieser fbreitwieser/networkD3/tree/add_zoom. Florian's branch added zooming capabilities to Sankey graphs, but was not merged into the CRAN package. Since that particular branch has not been updated since 2016, the syntax here differs than what should be used with the current (as of 2018-02-15) CRAN release.

    Welp, finally got it based on Sankey Diagram with R library networkD3 does not show colors

    The proper format for this usage is as follows.

    my_color <- 'd3.scale.category10().range(["blue", "blue" , "blue", "red", "red", "yellow", "purple", "purple"]).domain(["group_A", "group_B","group_C", "group_D", "group_E", "group_F", "group_G", "group_H"])'
    

    Another issue I finally figured out: group names in the domain can not have spaces!

    This would work:

    'd3.scale.category10().range(["blue", "red"]).domain(["group_A", "group_B"])'
    

    This would not!

    'd3.scale.category10().range(["blue", "red"]).domain(["group A", "group B"])'