【问题标题】:Large data set breaks d3 sankey diagram大数据集打破d3 sankey图
【发布时间】:2017-03-27 12:36:35
【问题描述】:

我正在根据https://bl.ocks.org/d3noob/5028304 中的示例制作 d3 桑基图。此示例适用于较小的数据集。当我切换到使用更大的数据集时,可视化会中断。看起来问题在于 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

【问题讨论】:

    标签: javascript jquery d3.js


    【解决方案1】:

    拥有 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

    【讨论】:

    • 节点填充是我的罪魁祸首。感谢您的回答!
    【解决方案2】:

    我也遇到了同样的问题。我有 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 =&gt; n.y1 - n.y0 &lt; 1); 执行额外过滤。我有一些情况,所有节点都有y1 - y0 &gt; 1000,但有2或3个节点有y1 - y0 &lt; 0.00000001

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

    【讨论】:

      猜你喜欢
      • 2013-09-05
      • 1970-01-01
      • 1970-01-01
      • 2022-10-01
      • 2015-02-17
      • 2018-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多