我的任务:给定一组 CSV 格式的数据,使用 D3 显示一个桑基图。
给定数据格式:(我无法更改)
Uses,Types,Feedback
Use1,Type1,Feedback1
Use2,Type1,Feedback1
Use2,Type2,Feedback1
...
D3 Sankey 插件所需的格式:
{ "nodes": [
{"name": "Use1"},
{"name": "Use2"},
{"name": "Type1"},
...
], "links": [
{"source":"Use1", "target":"Type1", "value":1},
...
}
我的问题:将 CSV 数据转换为 Sankey 图表所需的 JSON。我无法更改给我的初始数据,所以我必须动态构建 JSON。
我的研究将我带到了这里,但按摩 CSV 数据(尚未包含值,仅包含源和目标)的唯一示例是通过 MySQL。由于我无法访问项目中的数据库,因此我求助于使用 Underscore.js 来帮助我进行转换(在 Backbone.js 应用程序中)
这是我到目前为止所拥有的,它按预期工作。
// buildJSON is a method of a Backbone View that oversees the creation of the diagram
buildJSON: function( csv ) {
var json = {
nodes: [], // unique nodes found in data
links: [] // links between nodes
};
// get unique nodes!
var uniqueNodes = _.chain(csv).map(_.values).flatten().unique().value().sort();
uniqueNodes.forEach(function( node ) {
json.nodes.push({ name: node });
});
// map colors to nodes
this.color.domain(uniqueNodes);
// map links
var links = [];
var rMap = {};
var keys = _.keys(csv[0]);
for ( var i = 0; i < csv.length; i++ ) {
for ( var j = 0; j < keys.length - 1; j++ ) {
var relationship = csv[i][keys[j]] + '-' + csv[i][keys[j + 1]];
rMap[relationship] = ++rMap[relationship] || 1;
}
}
// create links from the linkmap
for ( var r in rMap ) {
if ( rMap.hasOwnProperty(r) ) {
var rel = r.split('-');
links.push({
source: rel[0],
target: rel[1],
value: rMap[r]
});
}
}
var nodeMap = {};
json.nodes.forEach(function( node ) { nodeMap[node.name] = node; });
json.links = links.map(function( link ) {
return {
source: nodeMap[link.source],
target: nodeMap[link.target],
value: link.value
};
});
return json;
}
对于小型数据集,这不会是一个问题,但数据可能包含数千行,可能多达 10 列。
所以,长话短说,我的问题分为两部分:
我可以实现任何明显的性能提升吗?
是否有更好(更有效)的方式来为 D3 中的桑基图按摩数据?
我意识到这是一个特别狭窄的问题,所以我感谢任何和所有的帮助!