D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
seantey
Full window
Github gist
SF Fire Department Calls Dec 2016, 12AM - 5AM
forked from
mbostock
's block:
Heatmap (2D Histogram, CSV)
<!DOCTYPE html> <meta charset="utf-8"> <style> body { font: 10px sans-serif; } .label { font-weight: bold; } .tile { shape-rendering: crispEdges; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } </style> <body> <script src="//d3js.org/d3.v3.min.js"></script> <script> function adjustTextLabels(selection) { selection.selectAll('.axis text') .attr("font-size","2em"); } var margin = {top: 40, right: 90, bottom: 30, left: 50}, width = 400 - margin.top - margin.bottom, height = 768 - margin.left - margin.right; var parseDate = d3.time.format("%m/%d/%Y").parse, formatDate = d3.time.format("%d"); //d3.scale.ordinal().rangeRoundBands([0, height], .05) var y = d3.time.scale().range([0,height]), x = d3.scale.linear().range([0, width]), z = d3.scale.linear().range(["#fee0d2", "#de2d26"]); // The size of the buckets in the CSV data file. // This could be inferred from the data if it weren't sparse. var yStep = 864e5, xStep = 1; var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); d3.csv("data_heatmap.csv", function(error, buckets) { if (error) throw error; // Coerce the CSV data to the appropriate types. buckets.forEach(function(d) { d.date = parseDate(d.date); d.time_hour = +d.time_hour; d.count = +d.count; }); // Compute the scale domains. y.domain(d3.extent(buckets, function(d) { return d.date; })); x.domain(d3.extent(buckets, function(d) { return d.time_hour; })); z.domain([0, d3.max(buckets, function(d) { return d.count; })]); // Extend the y- and x-domain to fit the last bucket. // For example, the x-bucket 3200 corresponds to values [3200, 3300]. y.domain([y.domain()[0], +y.domain()[1] + yStep]); x.domain([x.domain()[0], x.domain()[1] + xStep]); // Display the tiles for each non-zero bucket. // See https://bl.ocks.org/3074470 for an alternative implementation. svg.selectAll(".tile") .data(buckets) .enter().append("rect") .attr("class", "tile") .attr("y", function(d) { return y(d.date); }) .attr("x", function(d) { return x(d.time_hour); }) .attr("width", x(xStep) - x(0)) .attr("height", -(y(0) - y(yStep))) .style("fill", function(d) { return z(d.count); }); // Add a legend for the color values. var legend = svg.selectAll(".legend") .data(z.ticks(14).slice(1).reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(" + (width + 25) + "," + (10-6 + i * 25) + ")"; }); legend.append("rect") .attr("width", 25) .attr("height", 25) .style("fill", z); legend.append("text") .attr("x", 26) .attr("y", 10) .attr("dy", ".8em") .text(String); svg.append("text") .attr("class", "label") .attr("x", width + 25) .attr("y", -7) .attr("dy", ".8em") .text("Count"); // Add an x-axis with label. svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + 0 + ")") .call(d3.svg.axis().scale(x).orient("top").ticks(5) .tickFormat(function(d,i) { return""; }) ); // remove the tick labels and add custom label later // Add a y-axis with label. svg.append("g") .attr("class", "y axis") .call(d3.svg.axis() .scale(y) .ticks(d3.time.days) .tickFormat(formatDate) .orient("left")); // On y axis, Adjust tick marks svg.selectAll(".y text") .attr("transform","translate(0,10)"); // On y axis, Remove the extra 01 tick // The index for that tick is 37 // Careful this index changes easily!! svg.selectAll(".tick") .filter(function (d,i) { return i === 37; }) .remove(); // Add label for y axis svg.append("text") .attr("class", "label") .attr("y", 6) .attr("dy", "-32") .attr("dx", "-298") .attr("font-size", "16px") .attr("text-anchor", "middle") .attr("transform", "rotate(-90)") .text("Day of month (Dec 2016)"); // Add Dec 2016 - remove because seem weird // svg.append("text") // .attr("dy","-21px") // .attr("dx","-40px") // .attr("font-size", "13px") // .attr("font-weight","800") // .text("Dec"); // svg.append("text") // .attr("dy","-8px") // .attr("dx","-40px") // .attr("font-size", "13px") // .attr("font-weight","800") // .text("2016"); //Add label for x axis svg.append("text") .attr("font-size", "14px") .attr("class", "label") .attr("x", width/2) .attr("y", "-28") .attr("text-anchor", "middle") .text("Call Receive Time"); xLabels = svg.selectAll(".x"); hour1 = xLabels.append("g"); hour1.append("text") .attr("transform","translate(25,-15)") .text("00:00AM -"); hour1.append("text") .attr("transform","translate(25,-5)") .text("00:59AM"); hour1.attr("transform","translate(-15,0)") .attr("class","hours"); hour2 = xLabels.append("g"); hour2.append("text") .attr("transform","translate(109,-15)") .text("01:00AM -"); hour2.append("text") .attr("transform","translate(109,-5)") .text("01:59AM"); hour2.attr("transform","translate(-32,0)") .attr("class","hours"); hour3 = xLabels.append("g"); hour3.append("text") .attr("transform","translate(194,-15)") .text("02:00AM -"); hour3.append("text") .attr("transform","translate(194,-5)") .text("02:59AM"); hour3.attr("transform","translate(-51,0)") .attr("class","hours"); hour4 = xLabels.append("g"); hour4.append("text") .attr("transform","translate(281,-15)") .text("03:00AM -"); hour4.append("text") .attr("transform","translate(281,-5)") .text("03:59AM"); hour4.attr("transform","translate(-71,0)") .attr("class","hours"); hour5 = xLabels.append("g"); hour5.append("text") .attr("transform","translate(368,-15)") .text("04:00AM -"); hour5.append("text") .attr("transform","translate(368,-5)") .text("04:59AM"); hour5.attr("transform","translate(-93,0)") .attr("class","hours"); }); </script>
https://d3js.org/d3.v3.min.js