d3.js graph code creating extra nodes

125 views Asked by At

I have a perfectly working graph with a number of dynamic filters. The only issue is there are these extra nodes showing up around the graph.

extra_nodes

All the links of the graphs are in accordance with the JSON Data:

var IDData = JSON.stringify([
  ["C2", "ID2", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C2", "C3", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C6", "C1", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C5", "ID4", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C1", "ID1", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C1", "P1", "Customer", "Phone", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C6", "P2", "Customer", "Phone", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C2", "C6", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C4", "C3", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 3],
  ["C1", "C2", "Customer", "Customer", '2015-1-1', "2015-1-1", 500.0, 1],
  ["C4", "ID3", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 3],
  ["C3", "ID3", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 3],
  ["C1", "C5", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 1]
]);

Below is the code used to iterate through it to render it in a format for making the graph.

    var galData = JSON.parse(IDData);
var startnodes = [];
var endnodes = [];
var startnodetype = [];
var endnodetype = [];
var SendTime = [];
var PayTime = [];
var Total_Amt = [];
var Depth = [];
galData.map(function(e, i) {
  startnodes.push(e[0]);
  endnodes.push(e[1]);
  startnodetype.push(e[2]);
  endnodetype.push(e[3]);
  SendTime.push(e[4]);
  PayTime.push(e[5]);
  Total_Amt.push(e[6]);
  Depth.push(e[7]);
});
var final_data = createNodes(startnodes, endnodes, startnodetype, endnodetype, SendTime,PayTime, Total_Amt, Depth);
makeGraph("#Network_graph", final_data);

Below is the create node function:

     function createNodes(startnodes, endnodes, startnodetype, endnodetype,SendTime, PayTime,Total_Amt,Depth) {
  var node_set = new Set();
  var links = [];
  var nodetype = d3.set();
  startnodes.forEach(function(src, i) {
    var tgt = endnodes[i];
    node_set.add({
      id: src,
      type: startnodetype[i]
    });
    node_set.add({
      id: tgt,
      type: endnodetype[i]
    });
    links.push({
      source: src,
      target: tgt,
      sendtime: SendTime[i],
      paytime: PayTime[i],
      total_amt: Total_Amt[i],
      depth: Depth[i],
      value: 1
    });
  });

  startnodetype.forEach(function(src, i) {
    var tgt_type = endnodetype[i];
    nodetype.add(src);
    nodetype.add(tgt_type);
  });

  var d3GraphData = {
    nodes: [...node_set.values()].map(function(d) {
      return {
        id: d.id,
        type: d.type,
        group: 1
      }
    }),
    links: links,
    nodetype: nodetype.values().map(function(d) {
      return {
        id: d.id,
        group: 1
      }
    })
  }
  return d3GraphData;

};

I have a feeling this is because of using:

    var node_set = new Set()

But I am not sure. Using d3.set() for the nodes did not render the graph.

Also , I feel the node_set is being populated correctly. Don't know why the extra nodes just randomly show up.

Below is the Jsfiddle.

1

There are 1 answers

0
Cyril Cherian On BEST ANSWER

The problem is because you are using set for making unique elements array.

But before you use set you must understand:

var mySet = new Set();

mySet.add(1);
mySet.add(5);
mySet.add(5);

will generate [1,5]//as expected

But when you do

var mySet = new Set();

mySet.add({id:1});//Line 1
mySet.add({id:5});//Line 2
mySet.add({id:1});//Line 3

will generate [{id:1}, {id:5}, {id:1}]//as not expected

The reason is object added in Line1 and Line 3 are two different objects, this is the reason why you getting unexpected nodes.(However you are expecting that 3rd object should not get added, because 1st object has id 1)

One way to fix it is use array.

 var node_set = [];

Before you add element into the array check if it exists using the id.

    if (!node_set.find(function(d){ return d.id == src})){
        //only add if any object with that id is not found
        node_set.push({
            id: src,
            type: startnodetype[i]
        });
    }

working code here