显示日期范围DC内的值的累计平均值
我试图继续建立一个棒球统计仪表板,似乎又一次撞上了墙。
我有一组表示记录游戏统计数据的记录,并希望用单个条形图制作条形图,该条形图表示页面上第一个图表中选定日期范围的击球平均数。
我在创建显示所选日期范围的累积命中总数的第一个图表方面获得了帮助。 方法是使用regularize_groupAll函数更改groupAll函数以响应all()函数调用而不是.value()。
方法1:
当试图使用相同的方法时,我配置了图表/组来计算每天的总平均贡献总额(在这个例子中,有三场比赛,每天击球员的平均每天为.500,但是到期在命中和绝对中不同的总数,每场比赛的贡献与累积平均值不同)。 这是不希望的,因为我希望图表显示所选时间段的实际平均值(如果选择了一个游戏,我希望图表显示.500,两个游戏也是一样,所有三个游戏的累计平均值相同可能的日期组合是.500)。
var avgChart = dc.barChart("#avg-chart");
function avg(totalAbs, dim) {
return dim.groupAll().reduceSum(function(d) {
return (d.h / d.ab) * (d.ab / totalAbs);
});
}
var totalAbs = abDim.groupAll().reduceSum(function(d){ return d.ab }).value();
var totalAvg = avg(totalAbs, abDim);
var regTotalAvg = regularize_groupAll(totalAvg);
avgChart
.width(200)
.height(HEIGHT + 30)
.x(d3.scale.ordinal().domain(["Avg"]))
.xUnits(dc.units.ordinal)
.y(d3.scale.linear().domain([0, totalAvg.value()]))
.yAxisLabel("")
.centerBar(true)
.dimension(abDim)
.brushOn(false)
.alwaysUseRounding(true)
.group(regTotalAvg);
avgChart.render();
方法2:
看过Reductio的文档后,我想我可以使用.groupAll(groupingFunction)。 部分解决问题的方法是使用该函数将当前日期的计算中包含之前所有日期的游戏。 我能够使用.sum(dh)函数获得正确的匹配数量,但我目前无法将计数修改为正确的数字(d.ab)。
groupAll = dateDim.groupAll();
var dateArray = [new Date( 2016,3,4) ,new Date( 2016,3,5) ,new Date( 2016,3,6)];
reducer = reductio()
.groupAll(function(record) {
var datesToInclude = new Array();
for(i = record.index; i < dateArray.length; i++) {
datesToInclude.push(dateArray[i]);
}
return datesToInclude;
})
.count(true)
.sum(function(d){ return d.h });
reducer(groupAll);
console.log(groupAll.value());
方法3:
方法3是尝试创建自定义reduce函数并将它们提供给groupAll()。reduce(reduceAdd,reduceRemove,reduceInitial)函数。 起初这种尝试没有产生图表。 添加一个.valueAccessor(function(p){return p.value.count> 0?p.value.total / p.value.count:0}); 调用函数结束时绘制的总平均值,但在设置断点后,我发现在移动画笔以过滤日期之后,reduceRemove函数从未被调用过。
var avgChart = dc.barChart("#avg-chart")
function reduceAdd(p, v) {
p.count += v.ab;
p.total += v.h;
return p;
}
function reduceRemove(p, v) {
p.count -= v.ab;
p.toal -= v.h;
return p;
}
function reduceInitial() {
return {
count: 0,
total: 0
};
}
var allAvg = dateDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial);
var totalAvg = allAvg.value()
console.log("Total avg total hit count" + totalAvg.total)
console.log("Total avg count ab count" + totalAvg.count)
var regTotalAvg = regularize_groupAll(allAvg);
avgChart
.width(200)
.height(HEIGHT + 30)
.x(d3.scale.ordinal().domain(["Avg"]))
.xUnits(dc.units.ordinal)
.y(d3.scale.linear().domain([0, totalAvg.total / totalAvg.count]))
.yAxisLabel("")
.centerBar(true)
.dimension(dateDim)
.brushOn(false)
.alwaysUseRounding(true)
.group(regTotalAvg)
.valueAccessor(function(p) {
return p.value.count > 0 ? p.value.total / p.value.count : 0
});
avgChart.render();
JSFiddle:https://jsfiddle.net/schins02/acchgsfL/
任何帮助将不胜感激,我希望这可以帮助我克服困难,并能够自己解决这种性质的问题。
当您使用Crossfilter计算平均值时,应使用Crossfilter逐步计算组件,然后在显示数据时计算平均值本身。 使用Reductio,您可以通过创建一个始终具有一个值的虚拟维度,然后基于该维度创建一个计算必要组件的组来创建组。 在你的例子中:
var avgDim = playerData.dimension(function(d) { return true; });
var avgGroup = avgDim.group();
var reducer = reductio();
reducer.value("ab").sum("ab")
reducer.value("h").sum("h");
reducer.value("bb").sum("bb");
reducer(avgGroup);
avgChart
.width(200)
.height(HEIGHT + 30)
.x(d3.scale.ordinal().domain(["Avg"]))
.xUnits(dc.units.ordinal)
.y(d3.scale.linear().domain([0, 1]))
.yAxisLabel("")
.centerBar(true)
.dimension(avgDim)
.brushOn(false)
.alwaysUseRounding(true)
.group(avgGroup)
.valueAccessor(function(p) {
return p.value.h.sum / ( p.value.ab.sum - p.value.bb.sum );
});
这里是小提琴:https://jsfiddle.net/esjewett/qmtL6221/1/
请注意,我不确定您的接球次数是否已经消除了散步。 我认为它包括散步并将其删除,因为在平均击球次数计算中,散步并不算作蝙蝠,但如果您的蝙蝠数量不包含散步,则不要这样做。
PS再看一下这个,你的方法3也可以。 问题是,正如你注意到的那样,过滤器不适用于你的组。 这是因为您在您要过滤的相同维度dateDim
上定义了您的组。 Crossfilter不会将过滤器应用于定义过滤器的相同尺寸。
上一篇: Display cumulative average of values within date range DC
下一篇: custom ordering in custom reduce functions in dc.js crossfilter.js