如何将表数据转换为d3js Sankey

时间:2019-01-31 05:45:06

标签: json d3.js sankey-diagram

我们有一个项目,我们通过一个多步骤的过程来处理数千个项目。我想创建一个多组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或加载文件的帮助。我很欣赏这些建议,但它们的方向完全错误。

1 个答案:

答案 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);