我试图在D3 sankey中订购节点。我希望将值较大的节点绘制得更高。
这是相关代码(based on d3 noob's code)片段,我尝试使用D3的内置排序功能来实现我想要的效果。结果不是我所期望的。
在检查sankey.js时,我并不完全清楚插件是如何命令节点的。任何有关该主题的建议都将受到赞赏。
//set up graph in same style as original example but empty
graph = {"nodes" : [], "links" : []};
data.forEach(function (d) {
graph.nodes.push({ "name": d.source });
graph.nodes.push({ "name": d.target });
graph.links.push({ "source": d.source,
"target": d.target,
"value": +d.value });
});
//try to sort the nodes and links before indexing them (not working)
graph.nodes.sort(function (a,b) {return d3.descending(a.value, b.value); });
graph.links.sort(function (a,b) {return d3.descending(a.value, b.value); });
// return only the distinct / unique nodes
graph.nodes = d3.keys(d3.nest()
.key(function (d) { return d.name; })
.map(graph.nodes));
// loop through each link replacing the text with its index from node
graph.links.forEach(function (d, i) {
graph.links[i].source = graph.nodes.indexOf(graph.links[i].source);
graph.links[i].target = graph.nodes.indexOf(graph.links[i].target);
});
//now loop through each nodes to make nodes an array of objects
// rather than an array of strings
graph.nodes.forEach(function (d, i) {
graph.nodes[i] = { "name": d };
});
答案 0 :(得分:6)
从sankey.js文件中的resolveCollisions()函数中删除以下行将停止更改节点的顺序:
function resolveCollisions() {
...
// nodes.sort(ascendingDepth); // commented this out to prevent node reordering
...
}
然后,节点将被垂直排序,但它们最初是填充的。因此,如果在推送数据之前先对节点进行排序,它们将按排序顺序显示。
答案 1 :(得分:4)
如果将布局iterations
值设置为零,则会按字母顺序(按名称)顺序获取节点:这对我来说效果很好。
var sankey = d3.sankey()
.nodeWidth(36)
.nodePadding(40)
.size([width, height])
.layout(0); /* <<<<<<< setting the iterations to zero */
答案 2 :(得分:0)
碰巧遇到了这种情况,它there's an abstraction of d3-sankey
(很遗憾)不是很简单的,它允许您设置任意订单(以及其他许多非标准的东西,例如组和周期):
var layout = d3.sankey()
.extent([[100, 10], [840, 580]]);
var diagram = d3.sankeyDiagram()
.linkColor(function(d) { return d.color; });
d3.json('uk_energy.json', function(energy) {
layout.ordering([
[
[
"supply^Indigenous",
"supply^Imports"
],
[],
[]
],
[
[
"primary^Natural gas",
"primary^Bioenergy & waste",
"primary^Coal",
"primary^Manufactured fuel",
"primary^Primary electricity",
"primary^Electricity",
"primary^Petroleum products",
"primary^Primary oils"
],
[
"stocks^*"
],
[]
],
[
[
"transfers^*",
"transform^Power stns",
"transform^Other transform",
"transform^Refineries"
],
[],
[
"sink^*"
]
],
[
[
"secondary^Natural gas",
"secondary^Bioenergy & waste",
"secondary^Coal",
"secondary^Electricity",
"secondary^Manufactured fuel",
"secondary^Heat sold",
"secondary^Petroleum products"
],
[
"own use^*"
],
[
"loss^*"
]
],
[
[
"use1^Other",
"use1^Industry",
"use1^Transport"
],
[],
[]
],
[
[
"use^Domestic",
"use^Public administration",
"use^Commercial",
"use^Agriculture",
"use^Miscellaneous",
"use^Unclassified",
"use^Iron and steel",
"use^Non-ferrous metals",
"use^Mineral products",
"use^Chemicals",
"use^Mechanical engineering etc",
"use^Electrical engineering etc",
"use^Vehicles",
"use^Food, beverages etc",
"use^Textiles, leather etc",
"use^Paper, printing etc",
"use^Other industries",
"use^Construction",
"use^Air",
"use^Rail",
"use^Road",
"use^National navigation"
],
[],
[]
]
]
);
d3.select('#sankey')
.datum(layout(energy))
.call(diagram);
});
根据the docs:
如果指定了排序,则将节点排序设置为指定的值并返回此布局。如果未指定排序,则返回当前值,默认为null。
排序为空时,将自动计算节点排序。
指定排序后,将直接使用它,并且不会进行等级分配或排序算法。排序结构具有三个嵌套列表:排序是一个图层列表,每个图层是一个带区列表,每个图层是一个节点ID列表。
AFAICT,示例中的插入符号(^
)表示groupName^nodeName
。
如果您已经深入到一个项目中,这可能没有特别的帮助,但是如果从头开始一个项目,这可能是我的第一个接洽对象。
答案 3 :(得分:0)
以下步骤可用于创建具有自定义节点顺序的sankey。
let data = {nodes:[],links:[]}
订购/排序所有节点的功能
const sankey = d3.sankey()
.size(graphSize)
.nodeId(d => d.id)
.nodeWidth(nodeWidth)
.nodePadding(0.5)
.nodeAlign(nodeAlignment)
.nodeSort(null) //creates sankey nodes as ordered in the data
let graph = sankey(data)