javascript D3 JSON 数据转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15912966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
D3 JSON data conversion
提问by alta
I have this JSON data structure:
我有这个 JSON 数据结构:
[
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" },
{ "dep": "d2", "name": "name1", "size": "size3" },
{ "dep": "d2", "name": "name1", "size": "size4" }
]
and I want to convert it to a nested structure like this:
我想将其转换为这样的嵌套结构:
{
"name": "root",
"children": [
{ "name": "d1",
"children": [
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" }
]
},
{ "name": "d2",
"children": [
{ "dep": "d2", "name": "name1", "size": "size3" },
{ "dep": "d2", "name": "name2", "size": "size4" }
]
}
]
}
... and further using it to make the Reingold–Tilford Tree. Can anyone point me to the right direction, I'm pretty new to D3!
...并进一步使用它来制作Reingold-Tilford 树。谁能指出我正确的方向,我对 D3 还很陌生!
回答by Christopher Chiche
The strategy is to create a new empty data structure corresponding to what you want, and then fill it by going through the whole original dataset. Here is the code:
策略是创建一个新的空数据结构,对应你想要的,然后通过遍历整个原始数据集来填充它。这是代码:
var data = [
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" },
{ "dep": "d2", "name": "name1", "size": "size3" },
{ "dep": "d2", "name": "name2", "size": "size4" }
]
var newData = {"name": "root", "children": {}}
data.forEach(function (d) {
if (typeof newData.children[d.dep] !== 'undefined') {
newData.children[d.dep].children.push(d)
} else {
newData.children[d.dep] = {"name": d.dep, "children": [d]}
}
})
newData.children = Object.keys(newData.children).map(function (key) {
return newData.children[key];
});
The assignment at the end is to transform the object into an array.
最后的赋值是将对象转化为数组。
Which gives the desired result for newData
:
这给出了所需的结果newData
:
{
"name": "root",
"children": [
{ "name": "d1",
"children": [
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" }
]
},
{ "name": "d2",
"children": [
{ "dep": "d2", "name": "name1", "size": "size3" },
{ "dep": "d2", "name": "name2", "size": "size4" }
]
}
]
}
jsFiddle:http://jsfiddle.net/chrisJamesC/eB4jF/
jsFiddle:http : //jsfiddle.net/chrisJamesC/eB4jF/
Note:This method does not work for nested structures. It will be way harder to do this for nested structures but you can always use a recursive function.
注意:此方法不适用于嵌套结构。对于嵌套结构执行此操作会更困难,但您始终可以使用递归函数。
EDIT:As suggested by @imarane in his answer, you can use the d3.nest()which is way better than my hand made solution. You might thus accept his answer. By playing with it, it even was really easy to have multiple levels of nest:
编辑:正如@imarane 在他的回答中所建议的,您可以使用d3.nest()这比我手工制作的解决方案要好得多。因此,您可能会接受他的回答。通过使用它,甚至可以很容易地拥有多层嵌套:
var data = [
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" },
{ "dep": "d2", "name": "name1"},
{ "dep": "d2"}
]
var newData = {
"key":"root",
"children":
d3.nest()
.key(function(d){return d.dep})
.key(function(d){return d.name})
.key(function(d){return d.size})
.entries(data)
}
Which give:
其中给出:
{"key":"root","children":[
{"key":"d1","values":[
{"key":"name2","values":[
{"dep":"d1","name":"name2","size":"size1"},
{"dep":"d1","name":"name2","size":"size2"}
]}
]},
{"key":"d2","values":[
{"key":"name1","values":[
{"dep":"d2","name":"name1"}
]},
{"key":"undefined","values":[
{"dep":"d2"}
]}
]}
]}
Which the following data structure (I hope better to understand the whole point):
其中以下数据结构(我希望更好地理解整点):
var data = [
{ "dep": "d1", "name": "name2", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" },
{ "dep": "d2", "name": "name1"},
{ "dep": "d2"}
]
JsFiddle:http://jsfiddle.net/chrisJamesC/eB4jF/2/
JsFiddle:http : //jsfiddle.net/chrisJamesC/eB4jF/2/
More on Nest:http://bl.ocks.org/phoebebright/raw/3176159/
更多关于 Nest:http : //bl.ocks.org/phoebebright/raw/3176159/
回答by imrane
another option is to use the nest method built into D3....
另一种选择是使用 D3 中内置的嵌套方法....
var nested = d3.nest()
.key(function(d,i){ return d.dep; })
.entries(data);
which outputs:
输出:
[
{
"key": "d1",
"values": [
{
"dep": "d1",
"name": "name1",
"size": "size1"
},
{
"dep": "d1",
"name": "name2",
"size": "size2"
}
]
},
{
"key": "d2",
"values": [
{
"dep": "d2",
"name": "name1",
"size": "size3"
},
{
"dep": "d2",
"name": "name2",
"size": "size4"
}
]
}
]
JsFiddle: http://jsfiddle.net/imrane/bSGrG/1/
JsFiddle:http: //jsfiddle.net/imrane/bSGrG/1/
回答by Xavier Guihot
Since d3-collection
has been deprecated in favor of d3.array
, we can use d3.groups
to achieve what used to work with d3.nest
:
由于d3-collection
已被弃用而支持d3.array
,我们可以使用d3.groups
来实现以前使用的内容d3.nest
:
var output = {
"name": "root",
"children": d3.groups(input, d => d.dep).map(([k, vs]) => ({ "name": k, "children": vs }))
};
For example:
例如:
var input = [
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" },
{ "dep": "d2", "name": "name1", "size": "size3" },
{ "dep": "d2", "name": "name1", "size": "size4" }
];
var output = {
"name": "root",
"children": d3.groups(input, d => d.dep).map(([k, vs]) => ({ "name": k, "children": vs }))
};
console.log(output);
<script src="https://d3js.org/d3-array.v2.min.js"></script>
回答by Andrew Kaiser
Hey guys I think I found a fairly simple solution. I accomplished a very nice nesting of a large dataset (400,000 rows) for a hierarchical bar chart in a very streamline way. It utilizes the Underscore library and an additional function _.nest
. Simply download and include the two libraries necessary
嘿伙计们,我想我找到了一个相当简单的解决方案。我以非常流畅的方式为分层条形图完成了一个大数据集(400,000 行)的非常好的嵌套。它利用 Underscore 库和一个附加功能_.nest
。只需下载并包含必要的两个库
src="underscore-min.js"
src="underscore.nest.js"
Then use the _.nest
function to create your structure. Here's my line:
然后使用该_.nest
函数创建您的结构。这是我的线路:
var newdata = _.nest(data, ["Material", "StudyName"]);
"Material"
and "StudyName"
are the columns I want to group my structure to.
"Material"
和"StudyName"
是我想我的组结构,以列。
There are other options to use this function if you need to accomplish more things but I will leave it like this
如果您需要完成更多事情,还有其他选项可以使用此功能,但我会保持这样
回答by pritesh
Use this. U can check the output in the console of the browser if u need.
用这个。如果需要,您可以在浏览器的控制台中检查输出。
function reSortRoot(root, value_key) {
//console.log("Calling");
for ( var key in root) {
if (key == "key") {
root.name = root.key;
delete root.key;
}
if (key == "values") {
root.children = [];
for (item in root.values) {
root.children.push(reSortRoot(root.values[item],
value_key));
}
delete root.values;
}
if (key == value_key) {
root.value = parseFloat("1");
delete root[value_key];
}
}
return root;
}
var testdata=[
{ "dep": "d1", "name": "name1", "size": "size1" },
{ "dep": "d1", "name": "name2", "size": "size2" },
{ "dep": "d2", "name": "name1", "size": "size3" },
{ "dep": "d2", "name": "name1", "size": "size4" }
];
var testJson = d3.nest()
.key(function(d) { return d.dep; })
.entries(testdata);
console.log(testJson);
var testRoot={};
testRoot.key = "Information";
testRoot.values = testJson;
testRoot = reSortRoot(testRoot, "name");
console.log(testRoot);