2012-10-17 6 views
11

Sto cercando di disegnare una mappa termica con D3 utilizzando i dati da un file CSV: questo è ciò che ho finoraDisegno heatmap con d3

Dato un file CSV:

row,col,score 
0,0,0.5 
0,1,0.7 
1,0,0.2 
1,1,0.4 

Ho uno SVG e codice come segue:

<svg id="heatmap-canvas" style="height:200px"></svg> 

<script> 
d3.csv("sgadata.csv", function(data) { 
    data.forEach(function(d) { 
    d.score = +d.score; 
    d.row = +d.row; 
d.col = +d.col; 
}); 
//height of each row in the heatmap 
//width of each column in the heatmap 
var h = gridSize; 
var w = gridSize; 
var rectPadding = 60; 

$('#heatmap-canvas').empty(); 

var mySVG = d3.select("#heatmap-canvas") 
.style('top',0) 
.style('left',0); 

var colorScale = d3.scale.linear() 
.domain([-1, 0, 1]) 
.range([colorLow, colorMed, colorHigh]); 

rowNest = d3.nest() 
.key(function(d) { return d.row; }) 
.key(function(d) { return d.col; }); 

dataByRows = rowNest.entries(data); 
mySVG.forEach(function(){ 
var heatmapRow = mySVG.selectAll(".heatmap") 
    .data(dataByRows, function(d) { return d.key; }) 
    .enter().append("g"); 

    //For each row, generate rects based on columns - this is where I get stuck 
    heatmapRow.forEach(function(){ 
    var heatmapRects = heatmapRow 
     .selectAll(".rect") 
     .data(function(d) {return d.score;}) 
     .enter().append("svg:rect") 
        .attr('width',w) 
     .attr('height',h) 
     .attr('x', function(d) {return (d.row * w) + rectPadding;}) 
     .attr('y', function(d) {return (d.col * h) + rectPadding;}) 
     .style('fill',function(d) { 
      if(d.score == NaN){return colorNA;} 
      return colorScale(d.score); 
       }) 

}) 
</script> 

Il mio problema è con il nesting. Il mio annidamento è basato su 2 chiavi, la prima riga (utilizzata per generare le righe), quindi per ogni riga, ci sono più chiavi annidate per le colonne e ognuna di queste contiene il mio punteggio. Non sono sicuro di come procedere cioè un ciclo su colonne e aggiungere rettangoli con i colori

Qualsiasi aiuto sarebbe apprezzato

risposta

11

Mentre si potrebbe usare un subselect (vedi d3.js building a grid of rectangles) per lavorare con i dati annidati in d3 non è davvero necessario in questo caso. Ho creato un esempio utilizzando i tuoi dati allo http://jsfiddle.net/QWLkR/2/. Questa è la parte fondamentale:

var heatMap = svg.selectAll(".heatmap") 
    .data(data, function(d) { return d.col + ':' + d.row; }) 
    .enter().append("svg:rect") 
    .attr("x", function(d) { return d.row * w; }) 
    .attr("y", function(d) { return d.col * h; }) 
    .attr("width", function(d) { return w; }) 
    .attr("height", function(d) { return h; }) 
    .style("fill", function(d) { return colorScale(d.score); }); 

Fondamentalmente si può semplicemente utilizzare il row e col per calcolare la posizione corretta delle piazze nel vostro heatmap.

+0

Ci scusiamo per l'estensione. Non sapevo se avrei dovuto postare questa come una nuova domanda, ma c'è un modo per ridimensionare i rettangoli in modo che si inseriscano nel div in cui vengono inseriti? se non c'è una larghezza predefinita per il div (cioè varia a seconda delle dimensioni dello schermo?) – by0

+0

Puoi semplicemente prendere la dimensione di 'div' immediatamente prima di disegnare la heatmap e poi calcolare l'altezza e la larghezza in base al numero di righe e colonne. – Bill

+0

Non posso prendere la dimensione del div se non è stato impostato, posso? – by0