如何将百分比列添加到dc.js数据表中?

时间:2018-10-18 17:07:23

标签: javascript dc.js crossfilter

我的dc.js dataTable只有两列,其中一列是数字。我需要添加第三列,该列具有相同的数字,但以占总数的百分比表示:

VENDOR   SCORE      PERCENT
-------  -----      -------
Charles  5          50.0 %  
Sarah    4          40.0 %
John     1          10.0 %

如果表是静态的,我只需要计算百分比并将它们添加到数据数组中,然后再将其传递给Crossfilter:

let sum = data.reduce((accum, d) => accum + d.score, 0);
data.forEach(d => { d.percent = 100 * d.score / sum; });

但是可以过滤数据(使用dc.js图表​​和selectMenus),例如,用户可以选择仅显示女性供应商,然后该表将仅显示Sarah ...,但原来的百分比是40%而不是将其重新计算为100%。

有什么办法可以解决这个问题?我想没有办法自动计算百分比。但是也许我可以向某个事件添加一个侦听器,该事件在过滤数据之后但在dc.js重绘表之前触发?


顺便说一句,以防万一,让事情变得更糟...更糟糕的是,我没有直接处理数据维度,而是将一个伪造的组传递给表(code borrowed from here) :

function filteredGroup(originalGroup, filterFunction) {
  return {
    all: () => originalGroup.all().filter(filterFunction),
    top: n => originalGroup.top(Infinity).filter(filterFunction).slice(0, n),
    bottom: n => originalGroup.top(Infinity).filter(filterFunction).slice(-n).reverse()
  };
}

let ndx = crossfilter(data);
let dim = ndx.dimension(d => d.vendor);
let grp = filteredGroup(dim.group().reduceCount(), d => d.value > 0);

dc.dataTable('#id')
  .dimension(grp)
  .group(d => d.someOtherField)
  .showGroups(true)
  .columns([d => d.vendor, d => d.score])
  ...

(我的实际数据数组将包含Charles的5个条目,Sarah的4个条目和John的1个条目。每个条目包含更多信息,例如日期和时间,这些信息在selectMenus中用于允许过滤。但是我需要表格上的汇总数据。这就是为什么我使用组而不是维度。)

1 个答案:

答案 0 :(得分:1)

实际上很容易做到。我已经失去了视野,一个“团体”并不是一个神奇的神奇事物。它只是一个具有3个函数的对象:all,它返回一个包含所有数据的数组,topbottom,它们执行相同的操作,但仅返回前N个或后N个元素。正如戈登在其评论中指出的那样,每次显示表格时都会调用这些函数。

因此,我只需要计算假组定义中的百分比:

function filteredGroup(originalGroup, filterFunction) {
  return {
    all: () => calc(originalGroup.all().filter(filterFunction)),
    top: n => calc(originalGroup.top(Infinity).filter(filterFunction)).slice(0, n),
    bottom: n => calc(originalGroup.top(Infinity).filter(filterFunction)).slice(-n).reverse()
  };
}

function calc(data) {
  let sum = data.reduce((accum, d) => accum + d.score, 0);
  data.forEach(d => { d.percent = 100 * d.score / sum; });
  return data;
}