d3.js如何从CSV或表格生成树形层次结构

6

I have a csv with the following data:

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并没有真正帮助我,我也找不到任何在我搜索过的地方进行转换的代码片段。

1个回答

11

根据你的其他问题,我假设你想在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]。还要注意的是,通常我们不需要嵌套最低级别,本例中为state。
现在,我们可以将这些数据提供给d3.hierarchy以获得用于可视化的层次结构。如果您查看文档,我们与示例具有相同的数据结构,除了我们的children包含在一个叫做“values”的属性中,而不是“children”。不必担心,d3.hierarchy允许我们设置包含子代的属性的名称:
引用: d3.hierarchy(data[, children]) ... 对于每个数据,从根数据开始调用指定的children访问器函数,并且必须返回一个表示子数据的数据数组,或者如果当前数据没有子数据,则返回null。如果未指定children,则默认为: 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>

这里有一个例子,包含一个实际的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.nestd3.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');
path {
  fill: none;
  stroke: steelblue;
  stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>


感谢您详细和清晰的回答!有没有一种方法可以查看具有子结构的层次数据或将其导出为JSON文件?使用检查,我可以看到像这样的数组数据:▾对象{ 键:“世界” 值:▾数组(2)[ 0: ▾对象{ 键:“美国” 值:▾数组(2)[ 0: ▾对象{ 世界:“世界” 国家:“美国” 州:“加利福尼亚州” } 1: ▸对象{世界:“世界”,国家:“美国”,州:“新泽西州”} - santoku
1
您可以在浏览器中使用console.log()语句查看层次结构,但将其复制到JSON可能会很困难,因为层次结构内部的对象存在许多循环引用。说实话,我不确定是否有方法可以解决这个问题(如果有的话,它是否仍然适用于d3分层布局)。 - Andrew Reid
请原谅我的新手问题。我已经成功将层次结构传递给了树形图,但仍然无法将其用于树状图。有什么问题吗?http://jsbin.com/xequpikomi/edit?html,output - santoku
这里只有两件事情,因为它实际上不适合在评论中,可以看这里:https://bl.ocks.org/Andrew-Reid/0ad13f7a4cfdb498a46e982488f067ea。 - Andrew Reid
很高兴我能够帮到你。 - Andrew Reid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接