我有一个包含以下数据的csv:
world,country,state
World,US,CA
World,US,NJ
World,INDIA,OR
World,INDIA,AP
我需要转换为树层次结构,如下所示:
{
"name": "World",
"children": [
{ "name": "US",
"children": [
{ "name": "CA" },
{ "name": "NJ" }
]
},
{ "name": "INDIA",
"children": [
{ "name": "OR" },
{ "name": "TN" }
]
}
] };
使用d3.nest我只能访问一个json数组,而不是一个名为' children'在里面。还有什么需要做的吗?阅读API并没有什么帮助,我无法找到一个代码片段,可以在我搜索的任何地方进行转换。
答案 0 :(得分:4)
根据您的其他question,我假设您要在d3分层布局中使用此分层数据
一旦被d3.csv / tsv / dsv等读取,你会得到一个包含如下对象的数组:
[
{ "world": "World","country": "US","state": "CA" },
{ "world": "World","country": "US","state": "NJ" },
{ "world": "World","country": "INDIA","state": "OR" },
{ "world": "World","country": "INDIA","state": "AP"}
]
我们可以使用d3 nest来获取d3层次结构(树,树状图等)布局的可用树的大部分内容:
{
"key": "World", "values": [
{
"key": "US", "values": [
{ "world": "World", "country": "US", "state": "CA" },
{ "world": "World", "country": "US", "state": "NJ" }
]
},
{
"key": "INDIA", "values": [
{ "world": "World", "country": "INDIA", "state": "OR" },
{ "world": "World", "country": "INDIA", "state": "AP" }
]
}
]
}
这是用:
var nestedData = d3.nest()
.key(function(d) { return d.world; })
.key(function(d) { return d.country; })
.entries(data);
这会产生一个数组,数组中的每个项目都是一个根。要使用d3.nest()获取json,我们需要获取数组中的第一个元素,在本例中为nestedData[0];
。另请注意,我们通常不需要嵌套最低级别,在这种情况下是状态
现在,我们可以将此数据提供给d3.hierarchy,以获得用于可视化的层次结构。如果你查看文档,我们就有一个与示例相同的数据结构,除了我们的子项包含在名为" values"而不是"孩子"。不用担心,d3.hierarchy允许我们设置包含子项的属性的名称:
d3.hierarchy(data [,children])
...
为每个数据调用指定的子访问器函数, 从根数据开始,必须返回一个数据数组 表示子节点,如果当前数据没有,则返回null 儿童。如果未指定子项,则默认为:
function children(d) { return d.children; }
因此,要获取d3.nest创建的上述数据,请将其提供给d3.hierarchy:
var root = d3.hierarchy(nestedData[0],function(d) { return d.values; })
现在我们有一个可以提供给任何d3层次布局的数据集:
var data = [
{ "world": "World","country": "US","state": "CA" },
{ "world": "World","country": "US","state": "NJ" },
{ "world": "World","country": "INDIA","state": "OR" },
{ "world": "World","country": "INDIA","state": "AP"}
];
var nestedData = d3.nest()
.key(function(d) { return d.world; })
.key(function(d) { return d.country; })
.entries(data);
var root = d3.hierarchy(nestedData[0], function(d) { return d.values; })
// Now draw the tree:
var width = 500;
var height = 400;
margin = {left: 10, top: 10, right: 10, bottom: 10}
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g").attr('transform','translate('+ margin.left +','+ margin.right +')');
var tree = d3.tree()
.size([height-margin.top-margin.bottom,width-margin.left-margin.right]);
var link = g.selectAll(".link")
.data(tree(root).links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkHorizontal()
.x(function(d) { return d.y; })
.y(function(d) { return d.x; }));
var node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
node.append("circle")
.attr("r", 2.5);
node.append("text")
.text(function(d) { return d.data.key; })
.attr('y',-10)
.attr('x',-10)
.attr('text-anchor','middle');

path {
fill:none;
stroke: steelblue;
stroke-width: 1px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
&#13;
Here's an example有一个实际的csv和更多的行和级别。
如果csv数据结构不同,包含父对,子对,那么一旦用d3.csv / tsv / dsv解析它就会看起来像这样:
[
{parent: "", name: "World"},
{parent: "World", name:"US"},
{parent: "World", name:"India"},
{parent: "India", name:"OR" },
{parent: "India", name:"AP" },
{parent: "US", name:"CA" },
{parent: "US", name:"WA" }
]
有了这个,我们可以使用d3.stratify
而不是d3.nest
和d3.hierarchy
的组合:
var data = [
{parent: "", name: "World"},
{parent: "World", name:"US"},
{parent: "World", name:"India"},
{parent: "India", name:"OR" },
{parent: "India", name:"AP" },
{parent: "US", name:"CA" },
{parent: "US", name:"WA" }
];
// manipulate data:
var root = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; })
(data);
// Now draw the tree:
var width = 500;
var height = 400;
margin = {left: 10, top: 10, right: 10, bottom: 10}
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g").attr('transform','translate('+ margin.left +','+ margin.right +')');
var tree = d3.tree()
.size([height-margin.top-margin.bottom,width-margin.left-margin.right]);
var link = g.selectAll(".link")
.data(tree(root).links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkHorizontal()
.x(function(d) { return d.y; })
.y(function(d) { return d.x; }));
var node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
node.append("circle")
.attr("r", 2.5);
node.append("text")
.text(function(d) { return d.data.name; })
.attr('y',-10)
.attr('x',-10)
.attr('text-anchor','middle');
&#13;
path {
fill: none;
stroke: steelblue;
stroke-width: 1px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
&#13;