我们有一个项目,我们通过一个多步骤的过程来处理数千个项目。我想创建一个多组Sankey图,以帮助可视化我们在流程中的位置。这是在浏览器中运行的,是客户端javascript。我遵循了this demo,并使其开始运行。
我面临的挑战是如何将数据表转换为Sankey图所需的链接和节点。在该示例中,传递到图表的数据的组织方式如下:
{ "nodes":[
{"node":0,"name":"node0"},
{"node":1,"name":"node1"},
{"node":2,"name":"node2"},
{"node":3,"name":"node3"},
{"node":4,"name":"node4"}
],
"links":[
{"source":0,"target":2,"value":2},
{"source":1,"target":2,"value":2},
{"source":1,"target":3,"value":2},
{"source":0,"target":4,"value":2},
{"source":2,"target":3,"value":2},
{"source":2,"target":4,"value":2},
{"source":3,"target":4,"value":4}
]}
我从项目中每个项目的元素原始数据开始,每个项目将具有以下(为清楚起见而被截断)列和样本值的列表:
ID Process Owner Decision Status
01 quick group1 retire done
02 standard group2 replace working
03 quick none none hold
04 quick group2 retire working
每列还有其他几列和值,但是我认为这是个主意。它来自ajax,并且为json格式(不是固定宽度的列),但这是常规结构。
如何将其转换为链接和节点?
我发现this thread询问的是同一件事(我认为),但是针对R的,我没有足够的经验来回答。
我已经用Google搜索了答案。我发现的大多数教程都假定您已获得节点/链接格式的数据。而且,就像上面的线程一样,我发现一对夫妇谈论R,php或SQL,它们将数据转换为节点和链接-我都不了解。
数据每天每小时更改一次,我希望能够将其加载到任何想随时检查的人身上。所以我需要一个自动化的解决方案。
我有原始数据和用于创建图的模型。我只是想念如何以编程方式转换数据。
编辑
我已经将原始数据存储到代码中。那不是问题。问题在于所有教程都假定您已经有了节点和链接。我每个项目都有一行。这些不是一回事。我不需要json,ajax或加载文件的帮助。我很欣赏这些建议,但它们的方向完全错误。
答案 0 :(得分:1)
更新
以下是包含您的数据的完整的Sankey图: Sankey diagram from multiple column csv
基于需求的进一步信息并改进代码,我想到了:
var keys = Object.keys(data[0]); //get the headers for the data
keys.splice(keys.indexOf('ID'), 1)//remove the IDs key
data.forEach(function(d){
keys.forEach(function (key, i){
if (d[key]!="none") { adduniquenodes(d[key]); } //add node if not "none"
var c = 1; //checks next column to the i
if (d[keys[i+c]]!= undefined && d[key] !== "none"){
while (d[keys[i+c]] === "none"){
c = c+1; //jump to next column if "none" found
}
graph.links.push ({
"source" : d[key],
"target" : d[keys[i+c]],
"value" : countvalues(key,d[key],keys[i+c],d[keys[i+c]])
});
}
})
});
function adduniquenodes(value) {
if (graph.nodes.indexOf(value) === -1){
graph.nodes.push(value);
}
}
function countvalues (sourcekey, source, targetkey, target) {
var c = 0;
data.forEach (function (d){
if (d[sourcekey] === source && d[targetkey]===target){
c++;
}
});
return c;
}
console.log(graph);
第一个答案:
这可能会有所帮助: 以下代码将每个流程,所有者,决策和状态分别作为唯一的节点和链接。
请注意,仍然不确定您想要什么值,因此我将1用作值。
graph = {"nodes" : [], "links" : []};
data.forEach(function(d){
adduniquenodes(d.Process);
adduniquenodes(d.Owner);
adduniquenodes(d.Decision);
adduniquenodes(d.Status);
graph.links.push ( {"source" : d.Process,
"target" :d.Owner,
"value" : countvalues('Process',d.Process,'Owner',d.Owner)
});
graph.links.push ( {"source" : d.Owner,
"target" :d.Decision,
"value" : countvalues('Owner',d.Owner,'Decision',d.Decision)
});
graph.links.push ( {"source" : d.Decision,
"target" :d.Status,
"value" : countvalues('Decision',d.Decision,'Status',d.Status)
});
});
function adduniquenodes(value) {
if (graph.nodes.indexOf(value) === -1){
graph.nodes.push(value);
}
}
function countvalues (sourcekey, source, targetkey, target) {
var c = 0;
data.forEach (function (d){
if (d[sourcekey] === source && d[targetkey]===target){
c++;
}
});
return c;
}
console.log(graph);