dc.js和crossfilter二级聚合到每小时平均计数

我试图稍微扩展这个问题中描述的问题:

dc.js和crossfilter减少每周每天的平均计数

我想绘制一天中每小时的平均计数。 我已经按照上面的解决方案,在自定义缩减中每天计算值,唯一的变化是以小时为单位的维度。 这似乎工作得很好,可以在下面的小提琴中看到:

http://jsfiddle.net/dolomite/6eeahs6z/73/

顶部条形图显示按小时计算的平均计数,下图显示按小时计算的总计数。 所以小时22的总数为47,平均数为4.2727 ......数据中有11天,所以这是正确的。

然而,当我点击周日排行图并过滤周日时,我得到的总计数为22小时4分,平均值为0.3636 ......计算平均值的分母仍然包括数据中的所有平日,无论我过滤的周日。 因此,虽然总计数已过滤为星期日只显示4,但它除以数据中的总天数,而要求只是除以过滤器中选择的任何一天/秒的数量。

我知道解决方案在于修改自定义减少,但我卡住了! 任何关于我哪里出错的指针都会非常感激。

hourAvgGroup = hourDim.group().reduce(
            function (p, v) { // add
                var day = d3.time.day(v.EventDate).getTime();
                p.map.set(day, p.map.has(day) ? p.map.get(day) + 1 : 1);
                p.avg = average_map(p.map);
                return p;
            },
            function (p, v) { // remove
                var day = d3.time.day(v.EventDate).getTime();
                p.map.set(day, p.map.has(day) ? p.map.get(day) - 1 : 0);
                p.avg = average_map(p.map);
                return p;
            },
            function () { // init
                return { map: d3.map(), avg: 0 };
            }
        )

function average_map(m) {
var sum = 0;
m.forEach(function(k, v) {
    sum += v;
});
return m.size() ? sum / m.size() : 0;
}

m.size()计算地图中键的数量。 问题是,即使每天有0个记录分配给它,键仍然存在,所以m.size()在分母中计数。 解决方案是在计数达到0时删除密钥。可能有更有效的方法来实现此目的,但最简单的解决方案是将一行添加到自定义缩减程序中的remove函数中,以便函数如下所示:

function (p, v) { // remove
  var day = d3.time.day(v.EventDate).getTime();
  p.map.set(day, p.map.has(day) ? p.map.get(day) - 1 : 0);
  // If the day has 0 records, remove the key
  if(p.map.has(day) && p.map.get(day) == 0) p.map.remove(day);
  p.avg = average_map(p.map);
  return p;
},

顺便说一下,我也建议不要在你的组中包括实际的平均和平均值计算。 请在dc.js图表valueAccessor计算它。 对于添加或删除的每个记录,减速器运行一次。 valueAccessor仅在每个过滤器操作中运行一次。

链接地址: http://www.djcxy.com/p/32707.html

上一篇: dc.js and crossfilter second level aggregation to average count per hour

下一篇: Crossfilter Grouping