fbreitwieser / sankeyD3

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

Added custom yOrderComparator function for vertical ordering of nodes #16

Closed simon-tietze closed 6 years ago

simon-tietze commented 6 years ago

Added a parameter to pass a custom node comparator function down to sankey-d3. Also had to change the included sankey-d3 code to actually use the comparator function.

Could help https://github.com/fbreitwieser/sankeyD3/issues/2 and https://github.com/fbreitwieser/sankeyD3/issues/6 if I understand them correctly.

fbreitwieser commented 6 years ago

Thanks for the contribution @bragil-massoud , I think that's a useful feature!

simon-tietze commented 6 years ago

You're welcome! Thanks for the package, I will use it a lot going forward.

atarashansky commented 4 years ago

Hi Simon, could you provide a quick demonstration how to use the yOrderComparator argument? I have a list of values I would like to sort my nodes by in the y-axis -- how would I do this using yOrderComparator? Thanks!

simon-tietze commented 4 years ago

An example would be the following function - it simply prioritizes nodes with a specific name and the sorts as the default (with orderByPath = false) would.

yOrderComparator = JS("function(a, b) { if (a.name === 'Priority') {return 1;}; if (b.name === 'Priority') {return -1;}; return a.y - b.y; }")

SchmidtPaul commented 2 years ago

Hi, sorry I am late and also afraid I still don't understand. I tried to create a useful reprex - could you please help me make it work with yOrderComparator?

links <- data.frame(
  source = c(0, 0, 0, 1, 2, 3, 4, 4),
  target = c(1, 2, 3, 4, 4, 4, 5, 6),
  value = c(2, 3, 4, 2, 3 , 4, 4, 5)
)

nodes <- data.frame(
  label = c("A1", "B1", "B3", "B2", "C1", "D1", "D2"),
  yOrder = c(1, 1, 3, 2, 1, 1, 2)
)

sankeyD3::sankeyNetwork(
  Links = links,
  Nodes = nodes,
  Source = "source",
  Target = "target",
  Value  = "value",
  NodeID = "label",
  # yOrderComparator = ?,
  fontFamily = "Arial",
  numberFormat = ",.1s",
  fontSize = 12)

image

As you can see I have a yOrder column in my nodes data.frame. Additionally I labelled the nodes accordingly. How would I now order the nodes vertically according to my yOrder column?

simon-tietze commented 2 years ago

Hi @SchmidtPaul ,

I would use yOrderComparator = htmlwidgets::JS("function(a, b) { return a.yOrder - b.yOrder; }")

however I am not entirely sure I understand the expected order of the B* components in the reprex correctly. Does this work for you?

Cheers, Simon

SchmidtPaul commented 2 years ago

Hi @simon-tietze thanks for replying! To address your point right away: In this reprex I really just wish the nodes to be in the order they are named from top to bottom. So, B1 on top, then B2 in the middle and B3 on the bottom. That's it (- same for D1 and D2). As you can see the order is different by default and I would have to rearrange them manually afterwards.

However, it seems it still does not work as I intended. While B1 is now on top, B3 is not on the bottom? ...then again D1 and D2 are correct. I feel like I missing something here.

links <- data.frame(
  source = c(0, 0, 0, 1, 2, 3, 4, 4),
  target = c(1, 2, 3, 4, 4, 4, 5, 6),
  value = c(2, 3, 4, 2, 3 , 4, 4, 5)
)

nodes <- data.frame(
  label = c("A1", "B1", "B3", "B2", "C1", "D1", "D2"),
  yOrder = c(1, 1, 3, 2, 1, 1, 2)
)

sankeyD3::sankeyNetwork(
  Links = links,
  Nodes = nodes,
  Source = "source",
  Target = "target",
  Value  = "value",
  NodeID = "label",
  yOrderComparator = htmlwidgets::JS("function(a, b) { return a.yOrder - b.yOrder; }"),
  fontFamily = "Arial",
  numberFormat = ",.1s",
  fontSize = 12)

image