D3.js 在dc.js中使用子列打印聚合数据

D3.js 在dc.js中使用子列打印聚合数据,d3.js,dc.js,crossfilter,D3.js,Dc.js,Crossfilter,我有以下表格中的数据: data = [..., {id:X,..., turnover:[[2015,2017,2018],[2000000,3000000,2800000]]}, ...]; data = [..., {id:X,..., turnover:{2015:2000000, 2017:3000000, 2018:2800000}}, ...]; 我的目标是在x轴上绘制一年,与当前通过y轴上的交叉过滤器选择的所有公司的平均营业额对比 每家公司记录的年份不一致,但应始终为三年 如

我有以下表格中的数据:

data = [..., {id:X,..., turnover:[[2015,2017,2018],[2000000,3000000,2800000]]}, ...];
data = [..., {id:X,..., turnover:{2015:2000000, 2017:3000000, 2018:2800000}}, ...];
我的目标是在x轴上绘制一年,与当前通过y轴上的交叉过滤器选择的所有公司的平均营业额对比

每家公司记录的年份不一致,但应始终为三年

如果有帮助,我可以将数据重新组织为以下形式:

data = [..., {id:X,..., turnover:[[2015,2017,2018],[2000000,3000000,2800000]]}, ...];
data = [..., {id:X,..., turnover:{2015:2000000, 2017:3000000, 2018:2800000}}, ...];
我是否能够进一步重组数据,使其看起来像:

[...{id:X, ..., year:2015, turnover:2000000},{id:X,...,year:2017,turnover:3000000},{id:X,...,year:2018,turnover:2800000}]; 
然后将提供一个解决方案


但是把公司分成不同的行对我正在做的其他事情没有意义

除非我弄错了,否则我称之为a,也就是带有数组键的维度

您希望每一行在其包含的每一年记录一次,但您只希望它影响此维度。您不希望在其他维度中多次观察该行,这就是您不希望展平的原因

对于原始数据格式,维度定义如下所示:

var yearsDimension = cf.dimension(d => d.turnover[0], true);
标记维度的键函数应该返回一个数组,这里是年数

这个特性仍然是相当新的,正如crossfilter所说,今年发现了一些。这些bug应该很容易避免。该功能已经得到了大量的使用,并且没有发现重大的错误

始终要注意标记维度,因为任何聚合的总和都将超过100%——在您的情况下为300%。但如果你在一年内对公司进行平均,这应该不是问题

标记和值对 问题的独特之处在于,您不仅每行有多个键,而且还有多个与这些键关联的值

虽然crossfilter标记标注功能非常方便,但它无法让您知道在缩小时查看的是哪个标记。此外,最强大和通用的组约简方法

但有一种更有效的方法可以一次减少整个交叉滤波器:

groupAll对象的行为类似于一个组,只是它被送入所有行,并且只返回一个bin。如果使用
dimension.groupAll()
将得到一个groupAll对象,该对象观察除该维度上的过滤器外的所有过滤器。如果需要观察所有筛选器的groupAll,也可以使用

以下是
groupAll.reduce()
的缩减函数的解决方案(为简洁起见,使用ES6语法),它将所有行缩减为一个年份=>{count,total}的对象

function avg_paired_tag_reduction(idTag, valTag) {
  return {
    add(p, v) {
      v[idTag].forEach((id, i) => {
        p[id] = p[id] || {count: 0, total: 0};
        ++p[id].count;
        p[id].total += v[valTag][i];
      });
      return p;
    },
    remove(p, v) {
      v[idTag].forEach((id, i) => {
        console.assert(p[id]);
        --p[id].count;
        p[id].total -= v[valTag][i];
      })
      return p;
    },
    init() {
      return {};
    }
  };
}
它将被输入每一行,并将循环该行中的键和值,生成每个键的计数和总数。它假定键数组和值数组的长度相同

然后,我们可以使用a将对象按需转换为dc.js图表所期望的{key,value}对数组:

function groupall_map_to_group(groupAll) {
  return {
    all() {
      return Object.entries(groupAll.value())
        .map(([key, value]) => ({key,value}));
    }
  };
}
使用以下功能:

const red = avg_paired_tag_reduction('id', 'val');
const avgPairedTagGroup = turnoverYearsDim.groupAll().reduce(
  red.add, red.remove, red.init
);
console.log(groupall_map_to_group(avgPairedTagGroup).all());
虽然可以计算运行平均值,但更有效的方法是,如上所述,计算计数和总数,然后告诉图表如何在值访问器中计算平均值:

chart.dimension(turnoverYearsDim)
  .group(groupall_map_to_group(avgPairedTagGroup))
  .valueAccessor(kv => kv.value.total / kv.value.count)

.

如何将此答案与以下内容结合起来:,其中返回维度的数组?-最终的目标是,我希望x轴使用日期,但y轴是营业额的平均值。是的,
reduceSum
只接受一个参数,并且所有交叉过滤器组的缩减都不知道您正在查看的阵列中的哪个标签。谁说没有什么新的东西?老实说,我想我以前没见过这个问题。我已经在上面发布了一些工作代码,今天晚些时候我会回来写一个解释。