复杂d3.nest()操作 [英] Complex d3.nest() manipulation
问题描述
我有一个数组数组,如下所示:
I have an array of arrays that looks like this:
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
数据格式。
I want to use d3.nest() or even just standard javascript to convert this data into a nested data structure that I can use with d3.partition. Specifically, I want to create the flare.json
data format found here.
我想用d3.nest对应于数组中的索引位置。注意, 1
在上面示例数据中的所有子数组中位于第一个位置;因此,它在树的根。在数组中的下一个位置有三个值, 2
, 3
和 7
,因此,根值 1
有3个子项。此时树的样子如下:
The levels of the json object I want to create with d3.nest() correspond to the index positions in the array. Notice that 1
is in the first position in all the subarrays in the example data above; therefore, it is at root of the tree. At the next positions in the arrays there are three values, 2
, 3
, and 7
, therefore, the root value 1
has 3 children. At this point the tree looks like this:
1
/ | \
2 3 7
在子阵列的第三个位置有四个值, 3
, 5
和 6
。这些孩子将成为树中的地方如下:
At the third position in the subarrays there are four values, 3
, 5
, and 6
. These children would be places into the tree as follows:
1
____|___
/ | \
2 3 7
/ \ / / \
3 6 6 3 5
如何使用d3.nest()产生这个数据结构?上面显示的示例数据的完整数据结构应如下所示:
How can I produce this data structure using d3.nest()? The full data structure with the example data I showed above should look like this:
{"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}
]}
]}
]}
$ b b
我试图转换我上面的数组数据结构使用这样(非常错误):
I'm trying to convert my array data structure above using something like this (very wrong):
var data = d3.nest()
.key(function(d, i) { return d.i; })
.rollup(function(d) { return d.length; })
我一直在敲我的头一个星期,试图了解我如何从数组数组生成这种层次结构。如果有人能帮助我,我会非常感谢。
I've been banging my head for a week to try and understand how I can produce this hierarchal data structure from an array of arrays. I'd be very grateful if someone could help me out.
@ meetamit在评论中的答案是好的,但在我的情况下,我的树太深,无法重复申请 .keys()
到数据,所以我不能手动写这样的函数。
@meetamit's answer in the comments is good, but in my case my tree is too deep to repeatedly apply .keys()
to the data, so I cannot manually write a function like this.
推荐答案
这里有一个更简单的函数,它使用嵌套的为
- 循环遍历每个数组的所有路径指令。
Here's a more straightforward function that just uses nested for
-loops to cycle through all the path instructions in each of your set of arrays.
为了更容易找到具有给定标签的子元素,我已将 children
实现为数据对象/关联数组,而不是编号数组。如果您想要非常强大,可以使用 d3.map 了解该链接中描述的原因,但如果你的标签实际上是整数,那不会是一个问题。无论如何,它只是意味着当你需要访问孩子作为一个数组(例如,对于d3布局函数),你必须指定一个函数,使数组的对象的值 - d3.values(object)
效用函数
To make it easier to find the child element with a given label, I have implemented children
as a data object/associative array instead of a numbered array. If you want to be really robust, you could use a d3.map for the reasons described at that link, but if your labels are actually integers than that's not going to be a problem. Either way, it just means that when you need to access the children as an array (e.g., for the d3 layout functions), you have to specify a function to make an array out of the values of the object -- the d3.values(object)
utility function does it for you.
关键代码:
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.
}
}
基本集群树状图图表方法:
http://fiddle.jshell.net/KWc73/
Implemented with your sample data array and a basic cluster dendogram charting method:
http://fiddle.jshell.net/KWc73/
已编辑以添加:
Edited to add: As mentioned in the comments, to get the output looking exactly as requested:
- 从默认根对象的children数组访问数据的根对象。
- Access the data's root object from the default root object's children array.
- Use a recursive function to cycle through the tree, replacing the children objects with children arrays.
像这样:
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/
这篇关于复杂d3.nest()操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!