heatmapdc.jscrossfilter

dc.js: show all domain x values in heatmap


Requirement

I'm trying to create a heatmap indicating the frequency of an event through the hours of the week. On the Y axis I have the days of the week and on the X axis I have the hours of the day. I want to see all the hours of the day on the X axis, even those that do not have any corresponding frequency.

Problem

Unfortunately I'm not able to find out a way to display all the hours of the day. The Crossfilter includes only the hours of the day with a corresponding frequency during the week.

Current graphic result

enter image description here

As you can see not all hours of the day are displayed.

Code

let name = [
        '0', // S
        '6', // M
        '5', // T
        '4', // W
        '3', // T
        '2', // F
        '1' // S
];

this.heatmapDimension= this.data_CrossfilterObject.dimension((d) => {
            return [+d.hour, d.day + '.' + name[d.day]];
        });

this.heatmapGroup= this.heatmapDimension.group().reduceSum((d) => d));

this.giornoOraDashboardItem.chart
        .dimension(this.heatmapDimension)
        .group(this.heatmapGroup)

Solution

  • The heatmap allows you to specify the x and y domains using .cols() and .rows() respectively.

    It doesn't work for filtering out data but it does work for making sure that rows/columns exist.

    In your case, since you are generating a string value for the y/row dimension, it would look like:

    .rows(d3.range(7).map(i => i + '.' + name[i]))
    .cols(d3.range(24))
    

    heatmap with assured columns

    Here is a demo fiddle with random data.

    Using day names

    Update: since your intention is to show day names, here is one way to do that.

    Day names:

    let name = [
            'Su',
            'M',
            'Tu',
            'W',
            'Th',
            'F',
            'Sa'
    ];
    

    Use the name directly in the dimension key accessor (no numeric prefix needed):

    const heatmapDimension= cf.dimension((d) => {
            return [d.hour, name[d.day]];
        });
    

    Specify the names, in reverse order, as the rows, and disable sorting of rows:

    .rows(name.reverse()).rowOrdering(null)
    

    (Reverse order is needed because the chart's zero is at the bottom.)

    screenshot with day names

    New fiddle.