var arrays = [[1,2,3,4,5],[1,6,7,5]]
我想使用d3.nest()或者甚至只是标准的javascript来将这些数据转换成一个嵌套的数据结构,我可以使用d3.partition.具体来说,我想创建这里找到的flare.json data format.
要使用d3.nest()创建的json对象的级别对应于数组中的索引位置.请注意,在上述示例数据中,1位于所有子阵列的第一个位置;因此,它是在树的根.在阵列中的下一个位置有三个值2,3和7,因此根值1有3个子节点.在这一点上,树看起来像这样:
1
/ | \
2 3 7
在子阵列中的第三个位置有四个值,即3,5和6.这些子节点将放在树中,如下所示:
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": 3,"children": [
{"label": 6,"children": [
{"label": 5}
]}
]}
]},{"label": 7,"children": [
{"label": 5}
]},{"label": 5}
]}
]}
]}
我试图使用这样的东西来转换我的数组数据结构(非常错误):
var data = d3.nest()
.key(function(d,i) { return d.i; })
.rollup(function(d) { return d.length; })
我一直在敲打我的头一个星期,尝试了解如何从一系列阵列生成这种层次结构的数据结构.如果有人能帮助我,我将非常感激.
@queryamit在评论中的答案是好的,但在我的情况下,我的树太深了,不能重复地使用.keys()到数据,所以我不能手动编写一个这样的函数.
解决方法
为了更容易地找到带有给定标签的子元素,我已经将子元素实现为数据对象/关联数组,而不是编号的数组.如果你想要真正强壮,可以使用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);
更新小提琴:
http://fiddle.jshell.net/KWc73/1/