Closed oingelsson closed 7 years ago
Interesting use case. IMO this is really just a heat map and I think you should be able to get dc.js to display it properly.
I'd suggest trying a fake group to ensure that the zeroes are represented in the crossfilter output:
https://github.com/dc-js/dc.js/wiki/FAQ#ensure-that-bins-exist-even-if-there-are-no-values-in-them
Let me know if you have trouble implementing this. If you can work up an example jsfiddle or block with the cells missing (forking one of the empties linked on the main page), I can give you an example with the cells showing.
@gordonwoodhull here is my fiddle solution: http://jsfiddle.net/ak007/h3rbo3v2/1/ 3,3 is missing on matrix
Hi, I've worked up an example using ensure_group_bins
- actually I made a slightly simpler one that takes an array of bins to ensure, rather than taking them as extra parameters.
function ensure_group_bins_array(source_group, bins) {
return {
all:function () {
var result = source_group.all().slice(0), // copy original results (we mustn't modify them)
found = {};
result.forEach(function(d) {
found[d.key] = true;
});
bins.forEach(function(d) {
if(!found[d])
result.push({key: d, value: 0});
});
return result;
}
};
};
Then we can produce a list of bins that we want by using d3.cross to produce a Cartesian product. d3.cross
isn't available in d3v3 but we can copy it:
function d3_cross(values0, values1, reduce) {
var n0 = values0.length,
n1 = values1.length,
values = new Array(n0 * n1),
i0,
i1,
i,
value0;
if (reduce == null) reduce = function(a,b) { return [a,b]; };
for (i0 = i = 0; i0 < n0; ++i0) {
for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) {
values[i] = reduce(value0, values1[i1]);
}
}
return values;
}
Create the fake group like this:
var rg2 = ensure_group_bins_array(rg, d3_cross([1,2,3,4],[1,2,3,4]));
There were also a few things which I found overcomplicated in your fiddle
Generally I don't think you should need to have more than two parts to your keys; putting all the data inside the key means you won't be reducing anything. usually the rest of the data gets reduced and put in the value. So the dimension key is just:
return [+xPoint, +yPoint];
And the key, value, and color accessors are just:
.keyAccessor(function(kv) {
return kv.key[0];
})
.valueAccessor(function(kv) {
return kv.key[1];
})
.colorAccessor(function(d) {
return d.value;
})
Likewise your renderlet just needs:
var val = d.key[2] == 0 ? "": (d.key[0] + d.key[1]);
(I was surprised that the heatmap doesn't already support labels!)
Here's a fork of your fiddle: http://jsfiddle.net/gordonwoodhull/fL89vtn4/12/
I hope this helped. Definitely another use case to consider when designing a better data model for dc.js.
I'm going to close this since I don't think anything needs to be added to the dc.js core to support this. I'll open another issue for heatmap labels.
Thank you for your help, Gordon :-)
I'm currently working on a project where we need to create a Risk Matrix
We have tried using the existing Heat Map but are having issues, as it won't show the tiles for the X and Y combinations that has no values. .
Furthermore the colors of the tiles should be static and not the result of the number within each tile.
We are therefore trying to assess how much work, it would take, to create a new Risk Matrix class instead of trying to fix the issues, that comes with using the Heat Map, for things it was not designed for.
As I'm fairly new to dc.js can anybody help me by explaining, what it would take, based on your experience, to do this.