繁体   English   中英

大数据集打破 d3 桑基图

[英]Large data set breaks d3 sankey diagram

我正在从https://bl.ocks.org/d3noob/5028304 中的示例制作 d3 Sankey 图。 此示例适用于较小的数据集。 当我切换到使用更大的数据集时,可视化就中断了。 看起来问题在于 dy 值变为负数。

在控制台中,错误是:

Error: <rect> attribute height: A negative value is not valid. ("-9.02557856272838")

它指向的代码是:

node.append("rect")
  .attr("height", function(d) { return d.dy; })

这可能是因为情节正在离开屏幕? 我查看了使用 d3 比例,但我不确定如何实现它们。 也许是这样的:

d3.scale.ordinal()
.domain(data.map(function(d) { return d.name; }))
.rangeRoundBands([0, height], .2);

或者也许有一种方法可以在数据集变大时缩小可视化,以便所有内容都适合容器。

这是我的代码: https : //plnkr.co/edit/hOjEBHhS7vfajD2wb8t9?p=preview

有 945 个节点和 2463 个链接,这不可能适合 740 像素高的容器。 不仅如此,您还必须问自己“这个数据可视化对拥有大量信息的读者有何用处?” . 但既然这不关我的事,你可以做几件事:

当然,第一个是过滤您的数据。 如果这不是一个选项,您可以增加容器高度:

height = 3000 - margin.top - margin.bottom;

并减少节点的填充:

var sankey = d3.sankey()
    .nodeWidth(36)
    .nodePadding(1)
    .size([width, height]);

结果在这个plunker: https ://plnkr.co/edit/Idb6ZROhq1kuZatbGtqg ? p = preview

但是,即使这不是一个选项,您也可以更改sankey.js代码,或者在懒惰的解决方案中,避免使用负数:

.attr("height", function(d) { return d.dy < 0 ? 0 : d.y; })

结果如下: https : //plnkr.co/edit/tpaMpK5yXwYh9MEo8hgn?p=preview

我遇到了同样的问题。 我有包含 50 个节点和 50 个链接的图表,但也有包含 1200 个节点和 1200 个链接的图表。 我尝试的第一件事是增加画布的宽度和高度。 因此,我根据图形深度增加了宽度,并根据节点最多的级别增加了高度。

然而,我最终得到了一些宽度过大或高度过大的边缘情况图。 所以我最终重新生成了图形,直到每个节点都有一个最小高度,并且直到链接节点之间的空间合理。

所以这就是我所做的:

class SankeyChart {
   sankeyGenerator;
   graph;
   width = 1000;
   height = 1000;

   constructor(private nodes, private links) {
      this.sankeyGenerator = sankey()
        .extent([[10, 10], [this.width - 10, this.height - 10]])
      this.draw();
   }

 
  private draw() {
    this.graph = this.getGraph();
    this.drawLinks(this.graph.links); // method that draw the links
    this.drawNodes(this.graph.nodes); // method that draw the nodes
  }


  private getGraph() {
    const graph = this.sankeyGenerator({nodes: this.nodes, links: this.links});

    const increaseWidth = graph.links.some(l => Math.abs(l.source.y1 - l.target.y0) > 4 * Math.abs(l.source.x1 - l.target.x0));
    const increaseHeight = graph.nodes.some(n => n.y1 - n.y0 < 1);
    if (increaseHeight) {
      this.height += 1000;
    }
    if (increaseWidth) {
      this.width += 1000;
    }
    if (increaseHeight || increaseWidth) {
      this.sankeyGenerator.extent([[10, 10], [this.width - 10, this.height - 10]]);
      return this.getGraph();
    }
    return graph;
  }

}

请注意,您可能希望对graph.nodes.some(n => n.y1 - n.y0 < 1);执行额外的过滤器graph.nodes.some(n => n.y1 - n.y0 < 1); . 我有一些情况,所有节点的y1 - y0 > 1000 ,但有 2 或 3 个节点y1 - y0 < 0.00000001

另请注意,每次为大图表调用getGraph()时,您可能会向类添加一个参数以将容器的大小增加 1000 像素以上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM