首页 > 解决方案 > 为什么我的 d3.treemap() 返回的数据有很大的差距?

问题描述

我正在尝试创建一个描绘预算数据的树状图。

预期:树形图中不应有任何间隙;描绘每个节点的所有矩形都应该像 SVG 中的乐高积木一样适合。

实际:我的树形图的矩形在我的 SVG 中没有很好地排列;见下图:

在此处输入图像描述

目前,我的数据集很浅,主要是我编造的虚拟数据。CSV文件的结构是:

在此处输入图像描述

这些是代码中的相关步骤:

第 1 步: 加载 CSV 文件后,我使用以下方法将其转换为层次结构d3.stratify()

`let dataStratified = d3
.stratify()
.id(function (d) {
  return d.Child;
})
.parentId(function (d) {
  return d.Parent;
})(results);`

第2步:然后我传递给分层布局,d3.treemap()

let myTreemap = (data) =>
d3.treemap().size([width, height]).padding(1).round(true)(
  d3
    .hierarchy(data)
    .sum((d) => d.data["Rs,millions"])
    .sort((a, b) => b.data["Rs,millions"] - a.data["Rs,millions"])
);

  const root = myTreemap(dataStratified);

第 3 步:使用这个Observable 笔记本作为指南,我开始构建树形图的叶子:

 const leaf = g
.selectAll("g.leaf")
// root.leaves() returns all of the leaf nodes
.data(root.leaves())
.enter()
.append("g")
.attr("class", "leaf")
// position each group at the top left corner of the rect
.attr("transform", (d) => `translate(${d.x0},${d.y0})`)
.style("font-size", 10);

第 4 步:并将其附加到我创建的 SVG 中:

// Now we append the rects.


 leaf
    .append("rect")
    .attr("id", (d) => d.data.id)
    .attr("fill", (d) => {
      while (d.depth > 1) d = d.parent;
      return color(d.data.data.Child);
    })
    .attr("opacity", 0.7)
    // the width is the right edge position - the left edge position
    .attr("width", (d) => d.x1 - d.x0)
    // same for height, but bottom - top
    .attr("height", (d) => d.y1 - d.y0)
    // make corners rounded
    .attr("rx", 3)
    .attr("ry", 3);

其余代码主要是样式和标签放置,所以我认为这与我的问题无关,但可以在这里查看:GithubCodeSandbox

标签: javascriptd3.jssvgtreemap

解决方案


错误大小的矩形是由于树形图的总值,您实际上是在父节点上再次将总数相加(因为它位于 CSV 列中)。

只有当它是叶节点时才应该求和(这意味着如果 obj 没有子节点)。简而言之,如果您在hierarchy.sum函数中检查子项,并且仅在没有子项的情况下求和,那么它应该正确计算总数

let dataHierarchy = d3
    .hierarchy(dataStratified)
    .sum(d => (d.children ? 0 : d.data["Rs,millions"]))
    .sort((a, b) => b.data["Rs,millions"] - a.data["Rs,millions"]);

推荐阅读