我正在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);
或许有一种方法可以缩小可视化,因为数据集会变大,以便所有内容都适合容器。
答案 0 :(得分:4)
有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; })
答案 1 :(得分:0)
我遇到了同样的问题。我有包含 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);
执行额外的过滤。我有几个例子,所有节点都有 y1 - y0 > 1000
,但有 2 或 3 个节点 y1 - y0 < 0.00000001
。
另请注意,每次为大图表调用 getGraph()
时,您可能会向类添加一个参数以将容器的大小增加 1000 像素以上。