如何将百分比列添加到 dc.js 数据表?
How can I add a percentage column to a dc.js dataTable?
我的这个 dc.js 数据表只有两列,其中一列是数字。我需要添加第三列,具有相同的数字,但表示为占总数的百分比:
VENDOR SCORE PERCENT
------- ----- -------
Charles 5 50.0 %
Sarah 4 40.0 %
John 1 10.0 %
如果 table 是静态的,我将只计算百分比并将它们添加到数据数组中,然后再将其传递给 Crossfilter:
let sum = data.reduce((accum, d) => accum + d.score, 0);
data.forEach(d => { d.percent = 100 * d.score / sum; });
但是可以过滤数据(使用 dc.js 图表和选择菜单),例如用户可以选择只显示女性供应商,然后 table 将只显示 Sarah...但使用她原来的百分比,40% 而不是重新计算为 100%。
有什么办法可以解决这个问题吗?我想没有办法自动计算百分比。但也许我可以为过滤数据后触发的某些事件添加一个侦听器,但在 dc.js 重绘 table?
之前
顺便说一句,以防万一……更糟的是,我没有直接使用数据维度,而是将一个假组传递给 table( ):
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 中用于允许过滤.但我需要 table 上的聚合数据。这就是我使用组而不是维度的原因。)
其实做起来很容易。我已经迷失了方向,"group" 并不是一个神奇的神秘事物。它只是一个具有 3 个函数的对象:all
,其中 returns 包含所有数据的数组,以及 top
和 bottom
,它们执行相同但仅返回第一个 N或最后 N 个元素。正如戈登在他的评论中指出的那样,每次显示 table 时都会调用这些函数。
所以,我只需要计算我在假组定义中的百分比:
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;
}
我的这个 dc.js 数据表只有两列,其中一列是数字。我需要添加第三列,具有相同的数字,但表示为占总数的百分比:
VENDOR SCORE PERCENT
------- ----- -------
Charles 5 50.0 %
Sarah 4 40.0 %
John 1 10.0 %
如果 table 是静态的,我将只计算百分比并将它们添加到数据数组中,然后再将其传递给 Crossfilter:
let sum = data.reduce((accum, d) => accum + d.score, 0);
data.forEach(d => { d.percent = 100 * d.score / sum; });
但是可以过滤数据(使用 dc.js 图表和选择菜单),例如用户可以选择只显示女性供应商,然后 table 将只显示 Sarah...但使用她原来的百分比,40% 而不是重新计算为 100%。
有什么办法可以解决这个问题吗?我想没有办法自动计算百分比。但也许我可以为过滤数据后触发的某些事件添加一个侦听器,但在 dc.js 重绘 table?
之前顺便说一句,以防万一……更糟的是,我没有直接使用数据维度,而是将一个假组传递给 table(
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 中用于允许过滤.但我需要 table 上的聚合数据。这就是我使用组而不是维度的原因。)
其实做起来很容易。我已经迷失了方向,"group" 并不是一个神奇的神秘事物。它只是一个具有 3 个函数的对象:all
,其中 returns 包含所有数据的数组,以及 top
和 bottom
,它们执行相同但仅返回第一个 N或最后 N 个元素。正如戈登在他的评论中指出的那样,每次显示 table 时都会调用这些函数。
所以,我只需要计算我在假组定义中的百分比:
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;
}