我希望在 dc.js 的多维数据集中绘制与连续变量关联的几个直方图。虽然使用 dc.barChart
组件很容易实现这一点,但我希望对这些直方图进行面积归一化。在我的例子中,bin 宽度是统一的,所以这减少了将每个 bin/group 中的总计数除以 (binWidth * totCounts)
的问题。
我能够绘制这些直方图的初始 View ,这些直方图使用以下几行进行了区域归一化:
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 相结合确实会产生区域标准化条形图。但是,当我开始过滤数据时,过滤后的数据并没有重新归一化。相反, View 始终通过未过滤数据集上原始区域归一化的镜头呈现数据。
虽然我明白为什么会这样——crossfilter 中的 reducer 函数仍在使用初始规范化……我真的不明白是否有任何合理且高效的方法来实现我正在寻找的东西……即,始终根据过滤后的数据集对 dc.js 绘图 View 进行重新规范化。在我看来,由于任何单个 bin/组的规范化都需要来自所有组 (totCounts) 的信息,因此没有增量/高性能的方法来定义减少函数以实现高效的交叉过滤。
我是否缺少一些明显的方法来实现我想要做的事情,或者这是我应该放弃能够在 crossfilter/dc.js 中实现的希望?我将不胜感激任何可能为我指明正确方向的意见。
最佳答案
我们在这里需要做的是将 totCounts
因素从 reduce 计算中剔除,以便它可以适应不断变化的总数。由于 crossfilter 以递增方式计算减少量,因此无法在总计发生变化时重新应用它。
幸运的是,条形图的 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));
})
关于dc.js - 使用 crossfilter/dc.js 绘制区域归一化条形图的有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42265571/