dc.js和交叉过滤器自定义valueAccesor [英] dc.js and crossfilter custom valueAccesor

查看:64
本文介绍了dc.js和交叉过滤器自定义valueAccesor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试按小时绘制平均计数,并且自定义的reduce函数几乎在这里起作用 https:// jsfiddle.net/dolomite/6eeahs6z/

I am attempting to chart average counts by hour and the custom reduce function is almost working here https://jsfiddle.net/dolomite/6eeahs6z/

有一个问题是某些时间没有活动,例如数据中可能有三个星期天,但只有两个星期天有活动:

There is an issue in that some hours have no activity, e.g. there may be three Sundays in the data but only two have activity:

日期,小时,计数

Sun 02/07/17,22,5

Sun 09/07/17,22,5, 3

数据包含日期25/07/17,但没有22小时的记录。因此,星期日22小时的正确平均值应该是2.66但目前的方法平均产生4。

The data contains the date 25/07/17 but has no records for hour 22. The correct average for hour 22 on Sunday should therefore be 2.66 but the current method is producing an average of 4.

因此,简而言之,我试图找出如何获得每小时的总计数,然后除以数据中的天数,无论所选日期是否有每小时记录。

So in short I'm trying to work out how to get total counts per hour and then divide by the number of days in the data, whether or not the selected day has a record for each hour.

当前小时尺寸和自定义缩减为:

The current hour dimension and custom reduce is:

hourDim = ndx.dimension(function (d) {
    return d.EventHour;
})

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);
                if(p.map.has(day) && p.map.get(day) == 0) p.map.remove(day);
                //p.avg = average_map(p.map);
                return p;
            },
            function () { // init
                return { map: d3.map() };
            }
        )

平均值在图表valueAccessor中的计算方式如下:

The average is computed in the chart valueAccessor as follows:

.valueAccessor(function(d){ return average_map(d.value.map)})

其中

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


推荐答案

万一有人试图做类似的事情,我创建了一个维来保存数据中的所有记录:

In case anyone is trying to do similar, I created a dimension to hold all records in the data:

allDim = ndx.dimension(function (d) {
        return typeof Modality === 'string';
})

然后创建了一个组来保存数据中唯一天数的映射:

Then created a group to hold a map of the number of unique days in the data:

 dayCountGroup = allDim.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);
                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);
                if(p.map.has(day) && p.map.get(day) == 0) p.map.remove(day);
                return p;
            },
            function () { // init
                return { map: d3.map() };
            }
        )

小时维度和分组为:

hourDim = ndx.dimension(function (d) {
    return d.EventHour;
})

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);
                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);
                if(p.map.has(day) && p.map.get(day) == 0) p.map.remove(day);

                return p;
            },
            function () { // init
                return { map: d3.map() };
            }
        )

然后在值我使用的条形图的访问器:

Then in the value accessor for the barchart i used:

.valueAccessor(function(d){ return sum_map(d.value.map)/size_array_of_maps(dayCountGroup.top(Infinity)) ? sum_map(d.value.map)/size_array_of_maps(dayCountGroup.top(Infinity)) : 0})

其中使用的两个函数是:

Where the two functions used are:

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

function size_array_of_maps(myObject) {
    var count = 0;

    myObject.forEach(function(key,value) {
            count += key.value.map.size();
    })
   return count;
}

我确定这里有很多多余的代码,但是小提琴似乎可以正常工作,以后我会整理一下:)

I'm sure there is a lot of redundant code here but the Fiddle seems to be working and I'll tidy it up later :)

https://jsfiddle.net/dolomite/6eeahs6z/126/

这篇关于dc.js和交叉过滤器自定义valueAccesor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆