我有一些带有日期(d
(和值(v
(的CrossFilter数据:
[
{d: "2013-07-26T00:00:00.000Z", v: 2.5}
{d: "2013-07-25T00:00:00.000Z", v: 2.64}
// ...and many more
[
我在Crossfilter(crossfilter2@1.4.5
(中创建了一个几个月的组:
months = cf.dimension((d) => {
const dateObj = new Date(d.d);
// use 1-12 instead of 0-11
return dateObj.getMonth() + 1;
});
monthsGroup = months.group();
因此, monthsGroup.all()
返回12个对象的数组,按月汇总。我希望这些对象包括最小,最大和中位数,以及第25%和第75个百分位。还原(reductio@0.6.3
(有助于开箱即用的最小,最大和中位数,因此我添加了一个自定义聚合器来添加第75%和25个百分位。
以下代码 works ,但是非常慢:
const monthReducer = reductio()
.valueList(d => d.v)
.min(true)
.max(true)
.median(true)
.count(true)
.custom({
add(p) {
const valueList = p.valueList;
p.p75 = getPercentile(valueList, 75);
p.p25 = getPercentile(valueList, 25);
return p;
},
remove(p) {
const valueList = p.valueList;
p.p75 = getPercentile(valueList, 75);
p.p25 = getPercentile(valueList, 25);
return p;
},
initial(p) {
p.p75 = undefined;
p.p25 = undefined;
return p;
},
});
如果我删除.custom
块,则更快。这运行了data
中每个项目的代码,这是不必要的,因为它只需要查看最终的valueList
即可。Reaductio有一个几乎记录的.post()
钩子,我认为在这里可以解决问题,但我无法正常工作。
更新:我得到了后处理的挂钩回调,但它无法按照我的期望。
我尝试使用我在来源中看到的无证件方法注册新的帖子处理器:
// register post-processing function to add percentiles
reductio.registerPostProcessor('addPercentiles', (prior) => {
const all = prior();
return () => {
const updated = all.map((e) => {
const valueList = e.value.valueList;
e.value.p75 = getPercentile(valueList, 75);
e.value.p25 = getPercentile(valueList, 25);
return e;
});
return updated;
};
});
并将其添加到post()
钩:
// run post-processing to add the 25th & 75th %iles
this.monthsGroup.post().addPercentiles()();
这似乎可以做我想要的,但只有一次。当将过滤器应用于另一个维度时,它不会重新运行帖子挂钩。
如果中位数仅是第50个百分点,那么获得第25和第75位应该是微不足道的。我觉得自己很亲密,但我显然做错了什么。如何将这些聚合添加到还原降低器?
一种解决方案是在呈现图表之前,只需手动添加分位数即可。我有一个formatData
函数确实需要日期/时间格式,并将数据重组以更友好。由于数组的每个元素中仍然可以使用valueList
,因此我只是添加了几行来计算其中的25%和27个百分位。
不是理想的,但非常容易!