【问题标题】:crossfilter.js - exclude facts from group based on separate dimensioncrossfilter.js - 根据单独的维度从组中排除事实
【发布时间】:2020-11-26 02:04:28
【问题描述】:

假设我在 dc.js scatterPlot 中绘制了以下交叉过滤器对象(简化)

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)

我目前所拥有的是来自here

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

当我不关心排除 direction: -1 时,所有尝试都破坏了我的交叉过滤器,例如

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

【问题讨论】:

    标签: javascript mapreduce dc.js crossfilter


    【解决方案1】:

    您的维度和组函数中的每个路径都必须返回一个值,否则 Javascript 中的默认返回值为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()

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

    .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);
    

    结合跳跃方向

    .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,您可以选择。

    【讨论】:

    • 你的答案总是很棒!谢谢,为乐于助人而投票,但考虑到它对我来说更简单,我接受了简化版本...我对更复杂的交叉过滤器操作感兴趣,你知道交叉过滤器自定义减速器功能的任何好的博客文章/教程吗?我查看了 api 文档,它非常密集
    • 据我所知,SO 答案是最好的文档。代替全面的文档,我试图让我的每个答案解释得比手头的任务所必需的多一点。 (我从来没有时间写书。;)crossfilter gotchas wikidc.js tutorials 也很好。如果您在那里找到好的资源,请告诉我!
    【解决方案2】:

    最终使用归约...基于this post

    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;
    })
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 2021-03-16
      • 2015-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-30
      相关资源
      最近更新 更多