I have a problem trying to display a graph using a force layout. I use two csv files, one for vertices and one for edges. I am not sure, but I think that since the d3.csv method is asynchronous and I use two of them, I need to insert it into the other to avoid the problems of "concurrency" (initially I tried to call d3.csv twice and separately, and I had problems).
The structure of my csv is as follows:
For ribs:
source,target 2,3 2,5 2,6 3,4
For nodes:
index,name 1,feature1 2,feature2 3,feature3
My initial attempt:
// create the force layout var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var node, linked; // we read the edges d3.csv("csvEdges.csv", function(error, data) { edg = data; // we read the vertices d3.csv("csvVertices.csv", function(error2, data2) { ver = data2; force.nodes(data2) .links(data) .start(); node = svg.selectAll(".node") .data(data2) .enter() .append("circle") .attr("class", "node") .attr("r", 12) .style("fill", function(d) { return color(Math.round(Math.random()*18)); }) .call(force.drag); linked = svg.selectAll(".link") .data(data) .enter() .append("line") .attr("class", "link"); force.on("tick", function() { linked.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }); });
But I get:
"TypeError: Cannot call method 'push' of undefined."
I do not know what the problem is; I think this is due to the push of links. I read that perhaps the problem is with the way d3 maps links to node objects (in this case my nodes have two fields). So I tried the following (I saw this in another question here):
// we read the edges d3.csv("csvEdges.csv", function(error, data) { edg = data; // we read the vertices d3.csv("csvVertices.csv", function(error2, data2) { ver = data2; force.nodes(data2) .start(); //.links(data); var findNode = function(id) { for (var i in force.nodes()) { if (force.nodes()[i]["index"] == id) return force.nodes()[i] }; return null; }; var pushLink = function (link) { //console.log(link) if(findNode(link.source)!= null && findNode(link.target)!= null) { force.links().push ({ "source":findNode(link.source), "target":findNode(link.target) }) } }; data.forEach(pushLink); [...]
But in this case, I get a bunch:
Error: Invalid value for <circle> attribute cy="NaN"
and I donβt know what the problem is in this case!