in my case, I want to adjust dynamically the data range used in multiples histograms in my DC dashboard. Applying a filter on the graph 'cat' for instance, I expect the boundaries of the graph 'depth' to adjust using elasticX feature. But this is not the case.
Is there any way to adjust dynamically the depthRange and catRange after applying filters ? Many thanks for your support in advance.
HTML Code is as follows:
<div id="chart-depth">
<div>Depth</div>
<a class="reset" href="javascript:depthChart.filterAll();dc.redrawAll();" style="display: none;">reset</a>
<span class="reset" style="display: none;"><span class="filter"></span></span>
<br>
<br>
</div>
<div id="chart-cat">
<div>Cat</div>
<a class="reset" href="javascript:catChart.filterAll();dc.redrawAll();" style="display: none;">reset</a>
<span class="reset" style="display: none;"><span class="filter"></span></span>
<br>
<br>
</div>
<div id="dataTable" style="height: 300px;">
<div class='header'>
<span>Id</span>
<span>Cat</span>
<span>Depth</span>
</div>
</div>
JS Code is as follows:
//================================================================
points = [];
for (var i = 1; i < 100; i++) {
points.push({
Id: i,
Cat: Math.random()*120.,
Depth: Math.random() * 6000.
});
}
//================================================================
var filter;
var depthDimension;
var catDimension;
var depthGrouping;
var catGrouping;
//-----------------------------------
filter = crossfilter(points);
// Threshold has to be put on dimension not on group
// to get last bin filled with thresholded values
// Compare with https://jsfiddle.net/PBrockmann/ma3wr55k/
//-----------------------------------
depthRange = [0., 5000.];
catRange=[0.,100.];
depthBinWidth = 500.;
catBinWidth = 2.;
depthDimension = filter.dimension(function(d) {
// Threshold
var depthThresholded = d.Depth;
if (depthThresholded <= depthRange[0]) depthThresholded = depthRange[0];
if (depthThresholded >= depthRange[1]) depthThresholded = depthRange[1] - depthBinWidth;
return depthBinWidth * Math.floor(depthThresholded / depthBinWidth);
});
catDimension=filter.dimension(function(d){
// Threshold
var catThresholded = d.Cat;
if (catThresholded <= catRange[0]) catThresholded = catRange[0];
if (catThresholded >= depthRange[1]) catThresholded = catRange[1] - catBinWidth;
return catBinWidth * Math.floor(catThresholded / catBinWidth);
});
catGrouping=catDimension.group();
depthGrouping = depthDimension.group(); // by default reduceCount
//-----------------------------------
depthChart = dc.barChart("#chart-depth");
catChart=dc.barChart("#chart-cat");
dataTable = dc.dataTable("#dataTable");
//-----------------------------------
depthChart
.width(380)
.height(200)
.margins({
top: 10,
right: 20,
bottom: 30,
left: 30
})
.centerBar(false)
.elasticY(true)
.elasticX(true)
.dimension(depthDimension)
.group(depthGrouping)
.x(d3.scale.linear().domain(depthRange))
.xUnits(dc.units.fp.precision(depthBinWidth))
.round(function(d) {
return depthBinWidth * Math.floor(d / depthBinWidth)
})
.renderHorizontalGridLines(true);
xAxis_depthChart = depthChart.xAxis();
xAxis_depthChart.tickFormat(d3.format("d"));
yAxis_depthChart = depthChart.yAxis();
yAxis_depthChart.ticks(6).tickFormat(d3.format("d")).tickSubdivide(0); // tickSubdivide(0) should remove sub ticks but not
catChart
.width(380)
.height(200)
.margins({
top: 10,
right: 20,
bottom: 30,
left: 30
})
.centerBar(false)
.elasticY(true)
.elasticX(true)
.dimension(catDimension)
.group(catGrouping)
.x(d3.scale.linear().domain(catRange))
.xUnits(dc.units.fp.precision(catBinWidth))
.round(function(d) {
return catBinWidth * Math.floor(d / catBinWidth)
})
.renderHorizontalGridLines(true);
//-----------------------------------
dataTable
.dimension(depthDimension)
.group(function(d) {
return d.Id + " " + d.Cat + " " + d.Depth; // Data table does not use crossfilter group but rather a closure as a grouping function
})
.size(30);
//-----------------------------------
dc.renderAll();
I think what you're looking for here, in addition to
elasticX(true)
, is the ability to remove bins when they are empty.Crossfilter will still report the value zero for those bins which now aggregate to zero, and dc.js will faithfully plot them. I don't think we'd want to always assume that zeros should not be drawn, so we need to preprocess the data between crossfilter and dc.js to remove the empty bins.
The best technique, documented in the FAQ, is to create a "fake group" which wraps the crossfilter group and filters it.
Use it like so: