fbreitwieser / sankeyD3

D3 Sankey Network Graphs from R
67 stars 27 forks source link

Usage of linkGroup and linkColor #20

Open j-johanness opened 5 years ago

j-johanness commented 5 years ago

I have created a Sankey diagram using the sankeyD3 package, depicting land cover changes between 9 categories across 3 time-points. The main input to the plot was a *.csv file with 3 columns depicting 'source', 'target', and 'value'. Each node in a time-point is coloured individually using the d3.scaleOrdinal() .domain([ ]) .range([ ]) argument.

Right now, the colour of the links/flows are as per default (i.e. light grey). All flows share this colour. I wish to make it such that each link will be coloured as a gradient from the source color to the target colour. To do that, I would need to have 'linkGradient = TRUE' in my R script.

What I am struggling with is how to prepare my data such that I can use the 'linkGroup' and 'linkColor' arguments in the sankeyNetwork function. The sample code from this package does not incorporate those arguments (i.e. linkGroup, linkColor), as such, I have no template to adapt my script from. I can understand that I need to create a dataframe separate from the 'links' dataframe, specifically, I need to create this 'nodes' dataframe.

My 'nodes' dataframe is a .csv with 27 rows, each row indicating the node label for a land cover class in a time-point (maximum of 9 per time-point). I add another column in the .csv called 'linkColor' and in each cell, it contains the hexadecimal colour code for a specific node. E.g. For BRG 1996, this cell value is 'ffff66'. I adopt this method for writing the hexadecimal colour because it worked for me in the d3.scaleOrdinal() .domain([ ]) .range([ ]) argument. However, when I run the code (see below), nothing happens and the colour of the links are still as per default.

Looking for your kind help thank you.

Code:

` library(sankeyD3)

setwd(" ")

links <- read.csv("links.csv", header = TRUE, sep = ",")

nodes <- read.csv("names.csv", header = TRUE, sep =",")

links$source <- match(links$source, nodes$name)-1 # to zero-index the Sankey, if not it cannot be generated

links$target <- match(links$target, nodes$name)-1

Define colour for each individual node

my_color <- 'd3.scaleOrdinal() .domain ([ "BRG_1996", "BUA_1996","FOR_1996", "MNG_1996", "OPM_1996", "RPD_1996", "RBR_1996", "SHB_1996", "WTR_1996", "BRG_2007", "BUA_2007","FOR_2007", "MNG_2007", "OPM_2007", "RPD_2007", "RBR_2007", "SHB_2007", "WTR_2007", "BRG_2016", "BUA_2016","FOR_2016", "MNG_2016", "OPM_2016", "RPD_2016", "RBR_2016", "SHB_2016", "WTR_2016" ]) .range ([ "ffff66", "ff0000" , "246a24", "6666ff", "ff8000", "a65400", "ff00ff", "ccff66","66ccff", "ffff66", "ff0000" , "246a24", "6666ff", "ff8000", "a65400", "ff00ff", "ccff66","66ccff", "ffff66", "ff0000" , "246a24", "6666ff", "ff8000", "a65400", "ff00ff", "ccff66","66ccff" ])'

Plot the Sankey

margin <- c(top=0,right=0,bottom=0,left=0)

linkColor <- nodes$linkColor

linkGroup <- nodes$linkGroup

plot3 <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source", Target = "target", Value = "value", NodeID = "name", NodePosX = NULL, NodeValue = NULL, NodeColor = NULL, NodeFontColor = NULL, NodeFontSize = NULL, colourScale = my_color, fontSize = 10, fontFamily = "times-new-roman", fontColor = NULL, nodeWidth = 15, nodePadding = 10, nodeStrokeWidth = 1, nodeCornerRadius = 0, margin = NULL, title = "Ayeyarwady Region", orderByPath = FALSE, highlightChildLinks = FALSE, doubleclickTogglesChildren = FALSE, xAxisDomain = NULL, dragX = FALSE, dragY = FALSE, height = NULL, width = NULL, iterations = 0, zoom = FALSE, align = "none", showNodeValues = FALSE, linkType = "path1", #path1 is the easiest to see major fluxes curvature = 0.5, linkGroup = 'linkGroup', linkColor = 'linkColor', nodeLabelMargin = 5, linkOpacity = 0.3, linkGradient = TRUE, nodeShadow = FALSE, scaleNodeBreadthsByString = FALSE, xScalingFactor = 1, yOrderComparator = FALSE) plot3 `

SchmidtPaul commented 2 years ago

I know I'm two years late, but does this help?

links <- data.frame(
  source = c(0, 0, 1, 2),
  target = c(1, 2, 3, 3),
  value = c(10, 20, 10, 20),
  linkcolor = c("col1", "col1", "col2", "col2")
)

my_color <- 'd3.scaleOrdinal() .domain(["col1", "col2"]) .range(["blue", "#d12e69"])'

nodes <- data.frame(
  label = c("A", "B", "C", "D"),
  nodecolor = c("green", "green", "#E3B505", "#E3B505")
)

sankeyD3::sankeyNetwork(
  Links = links,
  Nodes = nodes,
  Source = "source",
  Target = "target",
  Value  = "value",
  NodeID = "label",
  LinkGroup = "linkcolor",
  colourScale = my_color,
  NodeColor = "nodecolor",
  numberFormat = ",.0f",
  fontFamily = "Arial",
  fontSize = 12,
  width  = 400,
  height = 300)

Created on 2021-12-22 by the reprex package (v2.0.1)