arm5077
arm5077

Reputation: 302

Keys not binding correctly to elements in D3

I'm having trouble updating data after binding values to SVG elements using a key in D3.

Here's an illustration. This is a sample CSV file I'm using to track drilling sites in PA.

name,lat,lng,company,production
1,40.543401,-79.162257,Shell,20000
2,40.608186,-79.369354,Shell,40000
3,40.558923,-79.630966,Shell,10000
4,40.431514,-79.466171,Range,25000
5,40.439876,-80.015488,Range,26000
6,42.173455,-80.513306,CNX,30000
7,39.927082,-74.788055,CNX,120000
8,40.045964,-75.10962,Chesapeake,15000
9,40.822611,-77.839508,Chesapeake,16000

I bind this data to g elements using this code:

d3.csv("data.csv", type, function(error, data) {
    wells = chart.selectAll(".well")
      .data(data, function(d){ return d.name; }).enter()
      .append("g")
      .attr("class", "well")
      .attr("id", function(d){ return d.name })
      .attr("transform", function(d){ return "translate(" + projection([d.lng, d.lat])[0] + "," + projection([d.lng, d.lat])[1] + ")"; } );

    wells.append("circle")
      .attr("r", 4);
});

Note that the key I'm binding that data on is name.

Introduce data2.csv, which is practically identical except the unique id is called well instead of name, and two of the lat-lng pairs are switched.

well,lat,lng,company,production
100,40.543401,-79.162257,Shell,20000
2,40.608186,-79.369354,Shell,40000
3,40.558923,-79.630966,Shell,10000
4,40.431514,-79.466171,Range,25000
5,42.173455,-80.513306,Range,26000
6,40.439876,-80.015488,CNX,30000
7,39.927082,-74.788055,CNX,120000
8,40.045964,-75.10962,Chesapeake,15000
9,40.822611,-77.839508,Chesapeake,16000

When I rebind data and update, nothing happens.

d3.csv("data2.csv", type, function(error, data2) {  
    var wells = chart.selectAll(".well")
      .data(data2, function(d){ return d.well; })
      .transition().duration(1000)
      .attr("transform", function(d){ return "translate(" + projection([d.lng, d.lat])[0] + "," + projection([d.lng, d.lat])[1] + ")"; } );
});

When I change well back to name in data2.csv, the animation works find and the two dots transpose. Why do the field names have to be the same?

Upvotes: 1

Views: 64

Answers (1)

musically_ut
musically_ut

Reputation: 34288

This is because of how the key argument to data function works. From the docs:

... the key function is invoked once for each element in the new data array, and once again for each existing element in the selection.

When it is called on the existing elements (which have data with field name and not well), it returns undefined and no nodes are selected for the update.

There are a couple of ways to correct this:

  1. Rename the fields and make them consistent. Recommended: it makes maintaining the code easier.
  2. Write the key function as: .data(data2, function (d) { return d.well || d.name; }). Less code, better for a one-off visualisation.

Upvotes: 2

Related Questions