Json 如何将表数据转换为d3js Sankey的节点和链接
我们有一个项目,我们正在通过一个多步骤的过程处理数千个项目。我想创建一个多组Sankey图,以帮助可视化我们在流程中的位置。这是在浏览器中运行的,是客户端javascript。我跟踪并启动了它 我面临的挑战是如何将数据表转换为Sankey图表所需的链接和节点。在该示例中,传递到图表的数据组织如下:Json 如何将表数据转换为d3js Sankey的节点和链接,json,d3.js,sankey-diagram,Json,D3.js,Sankey Diagram,我们有一个项目,我们正在通过一个多步骤的过程处理数千个项目。我想创建一个多组Sankey图,以帮助可视化我们在流程中的位置。这是在浏览器中运行的,是客户端javascript。我跟踪并启动了它 我面临的挑战是如何将数据表转换为Sankey图表所需的链接和节点。在该示例中,传递到图表的数据组织如下: { "nodes":[ {"node":0,"name":"node0"}, {"node":1,"name":"node1"}, {"node":2,"name":"node
{ "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格式(不是固定宽度的列),但这是一般结构
如何将其转换为链接和节点
我发现,这是问同样的事情(我想),但对R,我没有足够的经验来遵循答案
我在谷歌上搜索过答案。我找到的大多数教程都假设数据是节点/链接格式的。而且,像上面的线程一样,我发现有一些人在谈论将数据转换为节点和链接的R、php或SQL——我都不理解
数据每天每小时都在变化,我希望能够为任何想随时检查的人加载数据。所以我需要一个自动化的解决方案
我有原始数据和创建图表的模型。我只是缺少如何以编程方式转换数据
编辑
我已经在代码中输入了原始数据。这不是问题所在。问题是,所有教程都假设您已经有了节点和链接。我每件商品有一行。这不是一回事。我不需要json、ajax或加载文件方面的帮助。我很欣赏这些建议,但它们完全错了方向。更新 以下是完整的Sankey工作图和您的数据: 根据进一步的需求信息和改进规范,我提出了以下建议:
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);
我在下面添加了一个答案,以帮助您解析tsv数据。假设您的数据是以制表符分隔的,如上所示。如果您需要有关如何将数据拆分为节点和链接的更多帮助,那么您需要提供更多信息,以了解您所看到的节点以及您希望看到的链接。进一步阅读后,您可能希望每个ID都是路径和每个进程,所有者,将决策和状态作为节点,然后使用值1在每个节点之间进行链接?我的理解正确吗?这是一个正确方向的开始。价值是一个巨大的挑战,例如在你的链接[0]中,你有quick->group1。该值是多少“快速流程有组1”,但请注意,在我的示例中,我有一个“快速流程”,它直接保持状态。我还需要一个快速->保持。只是想进一步了解:您的流程列中是否也没有流程值,或者您的所有行是否都有流程值?您的行是否也有状态列值?您可以添加countvalues函数来计算值。我已经更新了答案以计算每个值。虽然这可能不是最好的代码,但可以肯定地进行优化。我添加了更新后的代码,该代码更短,更易于阅读,并且应该可以解决快速-->保持的问题。请查收。