crossfilter.js - 根据单独的维度从组中排除事实

crossfilter.js - exclude facts from group based on separate dimension

假设我要在 dc.js 散点图

中绘制以下交叉过滤器对象(简化)
var ndx = crossfilter([
  {time: 0.5, counts: 8, direction: 1},
  {time: 0.8, counts: 0, direction: -1},
  {time: 1.0, counts: 8, direction: 1},
  {time: 1.2, counts: 1, direction: -1},
  {time: 1.8, counts: 10, direction: 1},
  {time: 2.0, counts: 2, direction: -1},
  {time: 2.2, counts: 14, direction: 1},
  {time: 2.5, counts: 0, direction: -1},
  ...
]);

如何设置交叉滤波器以使输出向量为

x --> [0,1,2,...] 
y --> [8,9,14,...] // (average of all "1" direction transition counts, per whole integer time)

目前我所拥有的来自

const timeDim = ndx.dimension(d => d.time);
const binwidth = 1;
const timeHist = timeDim
  .group(d => {
    return binwidth * Math.floor(d / binwidth);
  })
  .reduceCount(); // I believe this only gives sum, but haven't gotten to averaging yet

当我不关心排除 方向时,这会起作用:-1,所有这样做的尝试都破坏了我的交叉过滤器,例如

const timeSignalDim = ndx.dimension(d => {
    if (d.direction === 1) {
      return d.time;
    }
  });

基于

最终使用reducio...
const binwidth = 1;
const timeDim = ndx.dimension(d => d.time);
const timeSignalGroup = reductio()
  .count(true)
  .sum(d => d.counts)
  .avg(true)
  .filter(d => {
    return d.direction === 1;
  })(
  timeDim.group(d => {
    return binwidth * Math.floor(d / binwidth);
  })
);

并通过 valueAccessor fxn 访问这些值

...
.valueAccessor(d => {
  return d.value.avg;
})

很高兴接受任何更优雅的回答!

维度和组函数中的每个路径都必须 return 一个值,否则 Javascript 中的默认 return 值为 undefined,即 can cause crossfilter to go off the deep end .

此外,无法拒绝维度或组键函数中的行。相反,您必须将拒绝的行减少到零:

const timeDim = ndx.dimension(d => d.time);
const binwidth = 1;
const timeHist = timeDim
  .group(d => {
    return binwidth * Math.floor(d / binwidth);
  })
  .reduceSum(d => d.direction > 0 ? 1 : 0);

这将计算所有正方向。相当于你回答中reductio的.filter().

Reductio 非常优雅,但只是为了比较,因为我在你发布答案之前就开始回答这个问题,所以计算平均值的直接交叉过滤器方法是

.reduce(
  (p,v) => { // add
    p.sum += v.counts;
    p.count++;
    return p;
  },
  (p,v) => { // remove
    p.sum -= v.counts;
    p.count--;
    return p;
  },
  () => ({sum: 0, count: 0}));

读数值时告诉图表计算比率:

chart.valueAccessor(({value: {sum,count}}) => sum / count);

结合跳跃方向 < 0:

.reduce(
  (p,v) => { // add
    if(v.direction > 0) {
      p.sum += v.counts;
      p.count++;
    }
    return p;
  },
  (p,v) => { // remove
    if(v.direction > 0) {
      p.sum -= v.counts;
      p.count--;
    }
    return p;
  },
  () => ({sum: 0, count: 0}));

Test fiddle.

同样,reductio 在底层做着几乎相同的事情。如果您想使用灵活的 EDSL 或直接使用 crossfilter,您可以选择。