1

I am building a heat map which displays the tweeting activity of an account during the week. My dataset is made of an array of dictonaries containing the weekday, the hour and the count of how many times the weekday+hour combination repeats. Since usually people stop tweeting during the night, there are some weekday+hour combinations which do not exist in the dataset. My problem is that when I draw the rectangles, I can only draw them for the existing combinations, and the non-existing ones remain blank. This is a link to the result, hopefully it'll make things clearer:

enter image description here

As you can see, there are blank spaces between 2:00 and 8:00 am.

I have no idea how to solve this problem, but I thought I could give a white background to the whole heat map before coloring the rectangles containing the existing combinations, so that the non-existing ones become white instead of being blank. How can i do this? If this is not possible, is there another solution to my problem?

This is my code:

[var data = timestamps_final;

var days = \["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"\], times = \["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"\];

var margin = { top: 40, right: 50, bottom: 40, left: 50 };

var w = Math.max(Math.min(window.innerWidth, 1000), 500) - margin.left - margin.right - 20,ngridSize = Math.floor(w / times.length), h = gridSize * (days.length + 2);

var svg = d3.select("#heat_map")
        .append("svg")
        .attr("width", w + margin.top + margin.bottom)
        .attr("height", h + margin.left + margin.right)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var colours = d3.scaleLinear()
        .range(\["#F0C881", "#F244C7", "#173490",\])
        .domain(\[1, 50, 100\]);

var dayLabels = svg.selectAll(".dayLabel")
        .data(days)
        .enter()
        .append("text")
        .text(function (d) { return d; })
        .attr("x", 0)
        .attr("y", function (d, i) { return i * gridSize; })
        .style("text-anchor", "end")
        .style('fill', 'white')
        .attr("transform", "translate(-6," + gridSize / 1.5 + ")")

var timeLabels = svg.selectAll(".timeLabel")
        .data(times)
        .enter()
        .append("text")
        .text(function (d) { return d; })
        .attr("x", function (d, i) { return i * gridSize; })
        .attr("y", 0)
        .style("text-anchor", "middle")
        .style('fill', 'white')
        .attr("transform", "translate(" + gridSize / 2 + ", -6)");

var rectangles = svg.selectAll("rect")
        .data(data)
        .enter()
        .append("rect")
        .attr("x", function (d) { return d.hour * 36; })
        .attr("y", function (d) { return d.weekday * 36; })
        .attr("width", 36)
        .attr("height", 36)
        .style("stroke-width", 1)
        .style("stroke", "white")
        .style("fill", function (d) { return colours(d.value); });

Thank you for your help.

rioV8
  • 24,506
  • 3
  • 32
  • 49
Stella
  • 11
  • 2
  • 1
    Possible duplicate of [How to set the background-color of a D3.js svg?](https://stackoverflow.com/questions/20142951/how-to-set-the-background-color-of-a-d3-js-svg) – Κωλζαρ Jan 29 '19 at 15:12
  • If you allow me to say, I believe you're viewing this problem by the wrong angle. You see, even if there is no tweets during the small hours, **those hours still exist**! That said, in a heat map it doesn't make sense removing those hours, because actually they have data: 0 tweets. Therefore, my suggestion is deleting this question and posting a new one asking how to fill the empty hours with 0 values, given your data (so, copy your data structure). That way, you'll have the rectangles, which will have the lightest colour in your scale. – Gerardo Furtado Jan 30 '19 at 02:03

1 Answers1

1

Add a big white rect before you add the week+hour rects

svg.append("rect")
    .style("fill", "white")
    .attr("width", 36 * 24)
    .attr("height", 36 * 7);

var rectangles = svg.selectAll("rect")
        .data(data)
        .enter()
        .append("rect")
        .attr("x", function (d) { return d.hour * 36; })
        .attr("y", function (d) { return d.weekday * 36; })
        .attr("width", 36)
        .attr("height", 36)
        .style("stroke-width", 1)
        .style("stroke", "white")
        .style("fill", function (d) { return colours(d.value); });
rioV8
  • 24,506
  • 3
  • 32
  • 49