使用crossfilter / dc.js绘制区域标准化条形图的有效方法?

时间:2017-02-16 05:19:43

标签: dc.js crossfilter

我希望在dc.js的多维数据集中绘制与连续变量相关的几个直方图。虽然使用dc.barChart组件很容易实现,但我希望将这些直方图区域规范化。在我的情况下,bin宽度是均匀的,因此这减少了将每个bin / group中的总计数除以(binWidth * totCounts)的问题。

我能够绘制这些直方图的初始视图,这些直方图是使用以下行中的某些内容进行规范化的:

var cf = crossfilter(data);
var totCounts = cf.groupAll().value();
var histDimension = cf.dimension(function(d) {
  return Math.floor(d.fieldOfInterest / binWidth) * binWidth;
});
var histGroup = histDimension.group().reduceSum(function(d) {
  return 1 / (binWidth * totCounts);
});

将此方法与dc.js耦合会导致区域标准化条形图。但是,当我开始过滤数据时,过滤后的数据不会重新规范化。相反,视图始终通过镜头显示未过滤数据集上原始区域标准化的数据。

虽然我理解为什么会这样 - 但是crossfilter中的reducer函数仍在使用初始规范化...我真的不明白是否有任何合理且高效的方法来实现我正在寻找的东西......即,使dc.js绘图视图始终相对于过滤的数据集重新规范化。在我看来,由于任何单个bin / group的规范化都需要来自所有组(totCounts)的信息,因此没有增量/高效的方法来定义减少函数以进行有效的交叉过滤。

我是否缺少一些明显的方法来实现我想要做的事情,或者这是我应该放弃希望能够在crossfilter / dc.js中实现的东西?我很感激任何可能使我指向正确方向的投入。

1 个答案:

答案 0 :(得分:2)

我们需要做的是减少计算中的因子totCounts,以便它可以适应不断变化的总数。由于交叉过滤器会逐步计算减少量,因此无法在更改时重新应用总量。

幸运的是,条形图的valueAccessor非常适合这一点。实际上,对于涉及除法的任何约简,它几乎总是更好的选择,因为当读取值(一次)与聚合和减少发生时(多次),执行除法会更有效率

这里我们只需要一种动态计算总数的方法,这就是groupAll非常适合的方法。在这种情况下,我们可能需要dimension.groupAll(),因为它不会观察当前维度的过滤器。我们不希望在当前图表上进行过滤,导致它不能合计为一个。

将这些放在一起:

var cf = crossfilter(data);
var histDimension = cf.dimension(function(d) {
  return Math.floor(d.fieldOfInterest / binWidth) * binWidth;
});
var totCounter = histDimension.groupAll();
var histGroup = histDimension.group(); // default reduceCount

barChart
    .valueAccessor(function(kv) {
        var total = totCounter.value();
        return total && (kv.value / (binWidth * total));
    })