Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3.js: "Cannot read property 'weight' of undefined" when manually defining both nodes and links for force layout

I tried setting both nodes and links at the same time this way:

var force = d3.layout.force()
    .size([w, h])
    .nodes(nodes)
    .links(connections)
    .start();

nodes = [{"name":"data_base_id", "kind":"subgenre"},...]
connections = [{"source":"name_of_node", "target":"name_of_other_node"},...]

I have data that may not have connections, so it is necessary to defined the nodes, so that all of the nodes get rendered. And defining the genres is pretty easy. but I get this error;

Cannot read property 'weight' of undefined

And when I comment out .links(connections) the graph renders (juts a bunch of dots scattered throughout...) How do I get the connections / links to cooperate with d3?

I was reading the docs, and apparently the source and target have to be INDEXES of the nodes in the nodes array. Is there anyway to change that? So, I can use the name of a node rather than the index it has in an array?

like image 296
NullVoxPopuli Avatar asked Jul 06 '12 07:07

NullVoxPopuli


4 Answers

I encounter same problem before, it is due to there is null values in source/target of links. print out nodes and links information might help to debug

like image 152
air_bob Avatar answered Nov 09 '22 05:11

air_bob


The force-directed layout uses edge weights to calculate the layout. Try adding a dummy "weight":1 to all of your connections.

The code that initializes the links looks like this:

links.forEach(function(d) {
    if (typeof d.source == "number") { d.source = nodes[d.source]; }
    if (typeof d.target == "number") { d.target = nodes[d.target]; }
});

Presumably you could tweak that (in the d3 source) to use any property/type.

like image 35
ZachB Avatar answered Nov 09 '22 05:11

ZachB


In addition to the answers mentioning the null in the source/target of links, the reason for this could be the assignment of an out-of-range source/target. E.g. you have 10 nodes and you assign the target to be the 11-th indexed node.

like image 12
elachell Avatar answered Nov 09 '22 07:11

elachell


Thanks to the answers above which refer to null source or target values!

I've been testing out the graph from http://bl.ocks.org/mbostock/4062045, and found that my data referenced a missing node.

This may help others debug this issue:

d3.json("my-buggy-data.json", function(error, graph) {

    // Find blank links, which give the error
    // "Uncaught TypeError: Cannot read property 'weight' of undefined"
    graph.links.forEach(function(link, index, list) {
        if (typeof graph.nodes[link.source] === 'undefined') {
            console.log('undefined source', link);
        }
        if (typeof graph.nodes[link.target] === 'undefined') {
            console.log('undefined target', link);
        }
    });

    force
        .nodes(graph.nodes)
        .links(graph.links)
        .start();
like image 10
ptim Avatar answered Nov 09 '22 05:11

ptim