Как добавить заголовки столбцов в сеть диаграмм СанкиD3

Я делаю диаграмму Санки и хочу добавить текст поверх каждого столбца, чтобы дать краткое описание того, что показано. Пример кода взят из галереи r-graph:

library(networkD3)

# A connection data frame is a list of flows with intensity for each flow
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 = unique(c(as.character(links$source), as.character(links$target)))
)

# With networkD3, connection must be provided using id, not using real name like in the links dataframe.. So we need to reformat it.
links$IDsource <- match(links$source, nodes$name)-1 
links$IDtarget <- match(links$target, nodes$name)-1

# Make the Network
p <- sankeyNetwork(Links = links, Nodes = nodes,
                   Source = "IDsource", Target = "IDtarget",
                   Value = "value", NodeID = "name", 
                   sinksRight=FALSE)
p

В функции networkD3::sankeyNetwork() для этого нет опции.

Я стремлюсь к чему-то, что выглядит примерно так:

введите описание изображения здесь


person User2321    schedule 26.03.2021    source источник


Ответы (1)


library(networkD3)
library(htmlwidgets)

# A connection data frame is a list of flows with intensity for each flow
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 = unique(c(as.character(links$source), as.character(links$target)))
)

# With networkD3, connection must be provided using id, not using real name like in the links dataframe.. So we need to reformat it.
links$IDsource <- match(links$source, nodes$name) - 1 
links$IDtarget <- match(links$target, nodes$name) - 1

# Make the Network
p <- sankeyNetwork(Links = links, Nodes = nodes,
                   Source = "IDsource", Target = "IDtarget",
                   Value = "value", NodeID = "name", 
                   sinksRight=FALSE)

htmlwidgets::onRender(p, '
  function(el) { 
    var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i);
    cols_x.forEach((d, i) => {
      d3.select(el).select("svg")
        .append("text")
        .attr("x", d)
        .attr("y", 12)
        .text("Step " + (i + 1));
    })
  }
')

введите описание изображения здесь


или установить метки вручную ...

htmlwidgets::onRender(p, '
  function(el) { 
    var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i);
    var labels = ["Step 2", "Step 1", "Step 3"];
    cols_x.forEach((d, i) => {
      d3.select(el).select("svg")
        .append("text")
        .attr("x", d)
        .attr("y", 12)
        .text(labels[i]);
    })
  }
')

введите описание изображения здесь

person CJ Yetman    schedule 29.03.2021
comment
Это потрясающе! Могу я попросить некоторых пояснений по поводу кода onRender, потому что в моей реальной диаграмме Шаг 2 появляется перед Шагом 1, к сожалению ... - person User2321; 29.03.2021
comment
Он создает массив уникальных значений узла x и циклически просматривает их, создавая текстовые элементы. Вы можете назвать их вручную, но тогда это не будет распространяться на другие случаи. - person CJ Yetman; 29.03.2021
comment
Это было бы хорошо (мой случай не очень универсален)! Не могли бы вы показать что-нибудь подобное, если это не проблема? Спасибо! - person User2321; 29.03.2021
comment
обновлен ручным примером - person CJ Yetman; 29.03.2021