JohnCoene / echarts4r

🐳 ECharts 5 for R
http://echarts4r.john-coene.com/
Other
600 stars 81 forks source link

Setting node color in e_sankey #314

Open domsle opened 3 years ago

domsle commented 3 years ago

I am trying to assign each node of sankey chart with a color.

In case of my data, looking like this:

sankey <- structure(list(source = c("a", "a", "a", "b", "b", "b", "c", 
"c", "c", "d", "d", "d", "e", "e", "e", "e", "f", "f", "f", "f"
), target = c("b", "c", "d", "e", "g", "f", "e", "g", "f", "e", 
"g", "f", "g", "h", "i", "j", "g", "h", "i", "j"), value = c(122912, 
2650044, 3279851, 90747, 32165, 0, 1687949, 90875, 871220, 2387145, 
202531, 690175, 450235, 807089, 499898, 2408619, 537129, 294937, 
455067, 274262), color = c("#440154FF", "#440154FF", "#440154FF", 
"#482878FF", "#482878FF", "#482878FF", "#3E4A89FF", "#3E4A89FF", 
"#3E4A89FF", "#31688EFF", "#31688EFF", "#31688EFF", "#26828EFF", 
"#26828EFF", "#26828EFF", "#26828EFF", "#1F9E89FF", "#1F9E89FF", 
"#1F9E89FF", "#1F9E89FF")), row.names = c(NA, -20L), class = "data.frame")

The resulting chart without any colors being set, works and looks like that:

sankey %>%
  e_charts() %>%
  e_sankey(source, 
           target, 
           value, 
           right = '10%',
           emphasis = list(focus = 'adjacency'),
           lineStyle = list(color = 'gradient', 
                            opacity = .3)) %>%
  e_tooltip()

image

If I would add colors e_add('itemStyle', color) to the code:

sankey %>%
  e_charts() %>%
  e_sankey(source, 
           target, 
           value, 
           right = '10%',
           emphasis = list(focus = 'adjacency'),
           lineStyle = list(color = 'gradient', 
                            opacity = .3)) %>%
  e_add('itemStyle', color) %>%
  e_tooltip()

I will get error of:

Error in `*tmp*`[[j]] : subscript out of bounds

Now after playing a bit with easier and simplier examples, I came to realise, that this is probably not as easy as each row's color being assigned to each source node (my initial assumption). When I plot just first 7 rows, it works, but the color of all nodes is exactly the same:

sankey[1:7,] %>%
  e_charts() %>%
  e_sankey(source, 
           target, 
           value, 
           right = '10%',
           emphasis = list(focus = 'adjacency'),
           lineStyle = list(color = 'gradient', 
                            opacity = .3)) %>%
  e_add('itemStyle', color) %>%
  e_tooltip()

image

I think that the problem is, that for whatever reason the colors are not translated into the right place in the chart object.

e_inspect on the code above results in these subsets of the whole object:

$series[[1]]$data
$series[[1]]$data[[1]]
$series[[1]]$data[[1]]$name
[1] "a"

$series[[1]]$data[[1]]$itemStyle
$series[[1]]$data[[1]]$itemStyle$color
[1] "#440154FF"

$series[[1]]$data[[2]]
$series[[1]]$data[[2]]$name
[1] "b"

$series[[1]]$data[[2]]$itemStyle
$series[[1]]$data[[2]]$itemStyle$color
[1] "#440154FF"

[TRUNCATED]

$series[[1]]$data[[7]]
$series[[1]]$data[[7]]$name
[1] "f"

$series[[1]]$data[[7]]$itemStyle
$series[[1]]$data[[7]]$itemStyle$color
[1] "#3E4A89FF"

For the record, I dont see any instance of label "f" or "b" with the colors that are assigned here.

My last attempt was creating a list with similar layout, and assigning it to the e_sankey's data argument, so it looks like that:

data = list(list(name = "a", itemStyle = list(color = NA_character_)), 
                       list(name = "b", itemStyle = list(color = "#3B5998")), 
                       list(name = "c", itemStyle = list(color = "#F56040")), 
                       list(name = "d", itemStyle = list(color = "#833AB4")), 
                       list(name = "e", itemStyle = list(color = NA_character_)), 
                       list(name = "f", itemStyle = list(color = NA_character_)))

But this does not solve the problem either, resulting in a chart object looking like that: image There are two lists named data inside of [['series']][[1]], but none of them contains the passed list.

Is it possible to set only some of the node's colors, while keeping the unset at the theme's default values?

As a side note I think that maybe the e_color could be a helpful here, but I think it is not a solution, since e_sankey does not accept factors.

JohnCoene commented 3 years ago

Ah, I see the issue. Let me think of possible solutions, the nested tree-like structure of the sankey makes this more difficult I think

helgasoft commented 3 years ago

If this is what you are after... sankey ...take a look at this code. It uses a different library, but can give you an idea on how to structure your data. BTW, your last attempt has correct node data, just have to find a way to replace the preset one.

Is it possible to set only some of the node's colors, while keeping the unset at the theme's default values?
Yes, you can define only colors for a,b,c,d, and leave e,f,g,etc. as default.