Dennis
Dennis

Reputation: 400

Nesting data using D3.js (heatmap)

So I am new to working with Javascript (especially the D3 library) and I am trying to do something not unlike the following example: http://mbostock.github.com/d3/talk/20111116/iris-splom.html. In my case though each cell is the same thing a 4 x 4 grid with exactly the same scale.

So in my case the top level element is a plate. Each plate has rows and columns at the intersection of a row and column a value (a heatmap if you will). I able to create the proper plate elements; however, the data for ALL plates is present under each element rather than properly nested. I tried to attach an image so you can see that each "plate" is the same, if you look at the underlying document structure it is the same and essentially each rectangle is two overlaid data points.

In looking more closely at Mike's example (link above), it looks like he uses a cross function to help out with the nesting of data, I am wondering if that is where my code falls down. Thank you for any help you all can provide.

I have posted my code below

    d3.csv("plateData.csv", function(data) {

  var m = 20,
      w = 400,
      h = 300,
      x_extent = d3.extent(data, function(d){return d.Rows}),
      y_extent = d3.extent(data, function(d){return d.Columns}),
      z_extent = d3.extent(data, function(d){return d.Values});


         var x_scale = d3.scale.linear()
             .range([m, w-m])
             .domain(x_extent)
        var y_scale = d3.scale.linear()
             .range([h-m,m])
             .domain(y_extent)   

        var ramp=d3.scale.linear()
                .domain(z_extent)
                .range(["blue","red"]);

    // Nest data by Plates
  var plates = d3.nest()
      .key(function(d) { return d.Plate; })
      .entries(data);   


  // Insert an svg element (with margin) for each plate in our dataset. 
var svg = d3.select("body").selectAll("svg")
      .data(plates)
        .enter().append("svg:svg")
      .attr("width", w)
      .attr("height", h)
//add grouping and rect 
    .append("svg:g")
    .selectAll('rect')
          .data(data)
          .enter()
     .append('svg:rect')
            .attr('x', function(d){return x_scale(d.Rows)})
            .attr('y', function(d){return y_scale(d.Columns)})
            .attr('width', 10)
            .attr('height', 10)
            .style('fill', function(d){return ramp(d.Values)});
  }
);

AND example Data:

Plate,Rows,Columns,Values
12345,1,1,1158.755
12345,1,2,1097.768
12345,1,3,1097.768
12345,1,4,914.807
12345,2,1,1189.249
12345,2,2,1128.261
12345,2,3,1433.197
12345,2,4,701.352
12345,3,1,914.807
12345,3,2,1433.197
12345,3,3,1189.249
12345,3,4,1402.703
12345,4,1,1158.755
12345,4,2,1067.274
12345,4,3,701.352
12345,4,4,1372.21
56987,1,1,20.755
56987,1,2,97.768
56987,1,3,97.768
56987,1,4,14.807
56987,2,1,89.249
56987,2,2,28.261
56987,2,3,33.197
56987,2,4,15.352
56987,3,1,2000.807
56987,3,2,14.197
56987,3,3,89.249
56987,3,4,402.703
56987,4,1,158.755
56987,4,2,3067.274
56987,4,3,701.352
56987,4,4,182.21

Upvotes: 0

Views: 1993

Answers (1)

Pablo Navarro
Pablo Navarro

Reputation: 8264

You problem has two sources:

  1. You are inserting one svg element for each nested group, but you don't have defined a position for each element (all the elements are in the body).

  2. You are selecting all the svg elements in the body, and appending one rectangle for each data element, without considering the nested structure.

One solution is to create one svg element inside the body, one group for each plate, define a position for each plate, translate the group to its position (in the svg element) and then create the rectangles for the heatmap.

Upvotes: 1

Related Questions