d3.js - 复杂的 d3.nest() 操作

标签 d3.js

我有一个数组,看起来像这样:

var arrays = [[1,2,3,4,5],
              [1,2,6,4,5],
              [1,3,6,4,5],
              [1,2,3,6,5],
              [1,7,5],
              [1,7,3,5]]

我想用d3.nest()甚至只是标准的 javascript 将这些数据转换为我可以与 d3.partition 一起使用的嵌套数据结构。 .

具体来说,我想创建这个 flare.json 数据格式。

我想用 d3.nest() 创建的 json 对象的级别对应于数组中的索引位置。请注意 1在上面的示例数据中位于所有子数组的第一个位置;因此,它位于树的根部。在数组的下一个位置有三个值,2 , 3 , 和 7 ,因此,根值 1有3个 child 。此时树看起来像这样:
      1
    / | \
   2  3  7

在子数组的第三个位置有四个值,3 , 5 , 和 6 .这些 child 将被放入树中,如下所示:
            1
        ____|___
       /    |    \
      2     3     7
     / \   /     / \
    3   6 6     3   5

如何使用 d3.nest() 生成此数据结构?带有我上面显示的示例数据的完整数据结构应如下所示:
   {"label": 1, 
     "children": [
        {"label": 2, "children": [
            {"label": 3, "children": [
                {"label": 4, "children": [
                    {"label": 5}
                ]},
                {"label": 6, "children": [
                    {"label": 5}
                ]}
            ]},
            {"label": 6, "children": [
                {"label": 4, "children": [
                    {"label": 5}
                ]}
            ]},
        {"label": 3, "children": [
            {"label": 6, "children": [
                {"label": 4, "children": [
                    {"label": 5}
                ]}
            ]}
        ]},
        {"label": 7, "children": [
            {"label": 3, "children": [
                {"label": 5}
            ]},
            {"label": 5}
        ]}
      ]}
    ]}

我正在尝试使用这样的东西(非常错误)转换上面的数组数据结构:
var data = d3.nest()
  .key(function(d, i) { return d.i; })
  .rollup(function(d) { return d.length; })

一个星期以来,我一直在绞尽脑汁,试图了解如何从数组数组中生成这种分层数据结构。如果有人可以帮助我,我将不胜感激。

@meetamit 在评论中的回答很好,但就我而言,我的树太深而无法重复应用 .keys()到数据,所以我不能手动编写这样的函数。

最佳答案

这是一个更直接的函数,它只使用嵌套 for -loops 循环遍历每组数组中的所有路径指令。

为了更容易找到具有给定标签的子元素,我实现了 children作为数据对象/关联数组而不是编号数组。如果你想变得非常健壮,你可以使用 d3.map由于该链接中描述的原因,但如果您的标签实际上是整数,那么这不会成为问题。无论哪种方式,这都意味着当您需要将子项作为数组访问时(例如,对于 d3 布局函数),您必须指定一个函数来从对象的值中创建一个数组—— d3.values(object) 效用函数为您完成。

关键代码:

var root={}, 
    path, node, next, i,j, N, M;

for (i = 0, N=arrays.length; i<N; i++){
    //for each path in the data array 
    path = arrays[i];
    node = root; //start the path from the root

    for (j=0,M=path.length; j<M; j++){
        //follow the path through the tree
        //creating new nodes as necessary

        if (!node.children){ 
            //undefined, so create it:
            node.children = {}; 
        //children is defined as an object 
        //(not array) to allow named keys
        }

        next = node.children[path[j]];
        //find the child node whose key matches
        //the label of this step in the path

        if (!next) {
            //undefined, so create
            next = node.children[path[j]] = 
                {label:path[j]};
        }
        node = next; 
        // step down the tree before analyzing the
        // next step in the path.        
    }    
}

使用您的示例数据数组和基本 cluster dendogram 实现制图方法:
http://fiddle.jshell.net/KWc73/

编辑添加:
如评论中所述,要使输出看起来完全符合要求:
  • 从默认根对象的子数组访问数据的根对象。
  • 使用递归函数循环遍历树,用子数组替换子对象。

  • 像这样:
    root = d3.values(root.children)[0];
    //this is the root from the original data, 
    //assuming all paths start from one root, like in the example data
    
    //recurse through the tree, turning the child
    //objects into arrays
    function childrenToArray(n){
        if (n.children) {
            //this node has children
    
            n.children = d3.values(n.children);
            //convert to array
    
            n.children.forEach(childrenToArray);
            //recurse down tree
        }
    }
    childrenToArray(root);
    

    更新的 fiddle :
    http://fiddle.jshell.net/KWc73/1/

    关于d3.js - 复杂的 d3.nest() 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20913689/

    相关文章:

    javascript - 将 Stringarray 交给 django 模板并在 d3 中使用它

    javascript - 将鼠标悬停时的文本添加到链接、添加过滤和缩放

    d3.js - d3 v4 forceSimulation 节点在 restart() 后不再移动

    javascript - 将动态工具提示添加到streamgraph d3.js

    svg - 如何使用 d3js 连接 map 上的坐标点?

    d3.js - 如何使用 d3.js 制作虚线图例

    javascript - d3-单击选择选项时更新条形图

    javascript - 具有从一个数据数组到多个数组的函数的 Enter() 语句? (添加多个渐变路径)

    d3.js - 在 D3 中使用 ONS map

    d3.js - d3 4.x 的 es6 模块导入失败