I have a 2d array of data that I'd like to visualize as a heatmap in D3.
From the examples I've seen, including:
https://stackoverflow.com/a/12925448/1647819
http://bl.ocks.org/2605010
it looks like you have to encode the row and column as attributes of each data element. Is there a way to take advantage of the structure of the data (i.e., the fact that it's a 2D array indexable with [i][j] notation) to avoid redundantly encoding the position information?
If not, is there a concise and/or efficient way to generate the data structure that encodes the position information? By that I mean something other than a nested for loop:
myData = [[1, 2], [3, 4]]
myDataWithPos = []
nRow = myData.length
nCol = myData[0].length
for (i = 0; i < nRow; i++){
for(j = 0; j < nCol; j++){
myDataWithPos.push({val: myData[i][j], row: i, col: j})
}
}
Sure, you can use the indices of a 2d array to draw a heatmap. I put together a quick example at http://jsfiddle.net/uArga/4/.
Assuming that your data looks like this:
var data = [[3,5],[9,2]];
First I set up some basic scales to calculate the x
and y
offsets based on the size of the data and the size of the chart. This makes it easy to resize the chart by changing the height
and width
without having to manually recalculate how big each of the cells should be.
var x = d3.scale.linear()
.range([0, width])
.domain([0,data[0].length]);
var y = d3.scale.linear()
.range([0, height])
.domain([0,data.length]);
You can then add each row to the heat map
var row = svg.selectAll(".row")
.data(data)
.enter().append("svg:g")
.attr("class", "row");
And then add each cell to the row using a subselect. There might be a cleaner way to do this but I basically just capture the row number alongside the data for each cell. I then use the scales to figure out the x
, y
, height
, and width
for each cell.
var col = row.selectAll(".cell")
.data(function (d,i) {return d.map(function(a){return {value: a, row: i};})})
.enter().append("svg:rect")
.attr("class", "cell")
.attr("x", function(d, i) { return x(i); })
.attr("y", function(d, i) { return y(d.row); })
.attr("width", x(1))
.attr("height", y(1))
.style("fill", function(d) { return colorScale(d.value); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With