【问题标题】:Add x-node titles to networkD3 Sankey plot in correct order以正确的顺序将 x 节点标题添加到 networkD3 Sankey 图
【发布时间】:2022-01-10 19:03:39
【问题描述】:

我正在尝试标记使用 networkD3 创建的 Sankey 图的 x 节点。

我在这里看到了一个解决方案:How to add columnn titles in a Sankey chart networkD3

但是,当我尝试手动设置标签时,它们显示的顺序错误。我将此作为该问题的评论发布,但被要求创建一个新问题。

这里有一个可重现的例子:

    library('tidyverse')
    library('networkD3')
    
    #create the dataframe
    df <- data.frame('location' = c('A', 'B', 'C', 'A', 'A', 'B'), 
                     'office' = c('D', 'E', 'E', 'E', 'F', 'G'), 
                     'strategy' = c('1', '2', '1', '1', '2', '5'), 
                     'tactic' = c('6', '6', '6', '7', '7', '7'), 
                     'target' = c('H', 'H', 'I', 'H', 'H', 'I'), 
                     'outcome' = c('K', 'L', 'L', 'L', 'L', 'L'), 
                     'output' = c('O', 'O', 'P', 'Q', 'Q', 'Q'))
    
    #prepare the data for Sankey using dplyr
    #Create the links
    links <- df %>%
        mutate(row = row_number()) %>%  
        pivot_longer(-row, names_to = "col", values_to = "source") %>% 
        mutate(col = match(col, names(df))) %>%  
        mutate(source = paste0(source, '_', col)) %>%  
        group_by(row) %>%
        mutate(target = lead(source, order_by = col)) %>%  
        ungroup() %>%
        filter(!is.na(target)) %>%  
        group_by(source, target) %>%
        summarise(value = n(), .groups = "drop")  
    
    #Create the nodes
    nodes <- data.frame(id = unique(c(links$source, links$target)),
                 stringsAsFactors = F) %>%
        mutate(name = sub('_[0-9]*$', '', id))
    
    #Create the source and target ID
    links$source_id = match(links$source, nodes$id) - 1
    links$target_id = match(links$target, nodes$id) - 1
    
    
    #Create the plot
    plot <- sankeyNetwork(Links = links, Nodes = nodes,
                  Source = 'source_id', Target = 'target_id', Value = 'value', NodeID = 'name',
                  fontSize = 14)
    
    #Apply the manual var labels - solution from the linked stackoverflow answer
    htmlwidgets::onRender(plot, '
      function(el) { 
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i);
        var labels = ["Location", "Office", "Strategy", "Tactic", "Target", "Outcome", "Output"];
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }
    ')

给予:

在这里你可以看到:
节点 1(“策略”)应为“位置”
节点 2(“战术”)应为“办公室”
节点 3(“位置”)应为“策略”
节点 4(“办公室”)应该是“战术”
节点 5(“目标”)是“目标”
节点 6(“结果”)是“结果”
节点 7(“输出”)是“输出”

不清楚这些是如何排序的。

我怎样才能以正确的顺序获得它们?

【问题讨论】:

    标签: javascript r d3.js htmlwidgets networkd3


    【解决方案1】:

    在 JavaScript 的第一行末尾添加.sort(function(a, b){return a - b}),比如...

    var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
    

    否则返回的列的 x 值可能是乱序的

    【讨论】:

    • 完美。感谢您对这个包的所有支持。
    • 抱歉,这实际上并不完全正确,因为 JavaScript 不会像人们期望的那样对数字进行排序....改用.sort(function(a, b){return a - b});...更新答案
    • 谢谢。即将回来,因为这对我的全部问题不起作用。这个更新的答案非常有效。
    猜你喜欢
    • 2022-10-17
    • 2019-02-13
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 2022-11-02
    • 2018-07-05
    相关资源
    最近更新 更多