Defining source between D3 plugin sankey.js and html code

1.1k views Asked by At

I'm attempting to create a Sankey diagram, and while I am now able to load my source codes, I am running into a slight issue between the sankey.js, and my html code.

When I run the HTML code, I get an error message like this: Uncaught TypeError: Cannot call method 'push' of undefined

This is where the error link directs me to:

// Populate the sourceLinks and targetLinks for each node. 
// Also, if the source and target are not objects, assume they are indices.  
function computeNodeLinks() {    
  nodes.forEach(function(node) {      
    node.sourceLinks = [];      
    node.targetLinks = [];    
  });
  links.forEach(function(link) {      
    var source = link.source,          
    target = link.target;      
    if (typeof source === "name") source = link.source = nodes[link.source];      
    if (typeof target === "name") target = link.target = nodes[link.target];      
    source.sourceLinks.push(link);      
    target.targetLinks.push(link);    
  });  
}

This is the input in the HTML code (my data is taken from a csv file).

//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
  });
});

My question is: is the sankey.js relying on the assumption that my data is from a json file?. If so, how can I adjust it so that it is compatible with a csv file? The data is saved as a csv file listed below:

source,target,value
Barry,Elvis,2
Frodo,Elvis,2
Frodo,Sarah,2
Barry,Alice,2
Elvis,Sarah,2
Elvis,Alice,2
Sarah,Alice,4
1

There are 1 answers

4
Lars Kotthoff On

You need to use either objects present in nodes or indices into nodes in the .source and .target of a link. It looks like you're using the strings from the CSV for this, which will break in the manner you have observed.

To fix, keep references to the objects you're creating and use those in the links:

data.forEach(function (d) {
      var source = { "name": d.source },
          target = { "name": d.target };
      graph.nodes.push(source);
      graph.nodes.push(target);
      graph.links.push({ "source": source,
                         "target": target,
                         "value": +d.value });
     });