问题描述
我一直在玩 crossfilter ,发现它很棒,但是最近撞墙了。我根本不知道我的问题是否需要 crossfilter ,很高兴听到任何替代解决方案。
I have been playing with crossfilter and found it great but hit into a wall recently. I don't know if my problem needs crossfilter at all, so happy to hear any alternatives solutions.
我的数据如下:
[{
year: "1987",
country: "UK",
product: "pineapple",
tons_available: 10,
tons_sold: 8
},
{ year: "1987", country: "US", product: "pineapple", tons_available: 34, tons_sold: 18},
{ year: "1987", country: "UK", product: "pear", tons_available: 4, tons_sold: 3},
{ year: "1987", country: "US", product: "pear", tons_available: 23, tons_sold: 20},
{ year: "1988", country: "UK", product: "pineapple", tons_available: 12, tons_sold: 3},
{ year: "1988", country: "US", product: "pineapple", tons_available: 56, tons_sold: 6},
{ year: "1988", country: "UK", product: "pear", tons_available: 32, tons_sold: 32},
{ year: "1988", country: "US", product: "pear", tons_available: 31, tons_sold: 8},
and on, and on...]
我想汇总年度数据,并能够针对 tons_available和 tons_sold等现有指标进行操作。
I want to aggregate yearly data and was able to do it for metrics already available like "tons_available" and "tons_sold".
var by_week = data_to_filter.dimension( function(d) { return d.year; });
var tons_sold_by_week = by_week.group()
.reduceSum(function(d) { return d.tons_sold; });
但是,我找不到在聚合对象之上创建指标的方法。例如,我想创建一个每年的销售率。为此,我需要每年汇总所有字段,然后仅进行除法:tons_sold / tons_available。
However, I cannot find a way to create metrics on top of the aggregated object. For example, I would like to create a sell-through-rate per year. For this, I would need to sum all the field per year and then only divide: tons_sold/tons_available.
这在理想情况下会给我一个json格式为:
This ideally would give me a json formatted as:
[{
year: "1987",
tons_available: 71,
tons_sold: 49
str: 0.69
},
{ year: "1988", tons_available: 131, tons_sold: 49, str: 0.37 },
and on, and on...]
在我看来,聚合对象仅保留求和变量和结果,每个变量仅包含一对键/值年。
It seems to me that the aggregated object only keep the summed variables and result with just one couple key/value per year.
有没有办法实现我所追求的目标?
Is there way to achieve what I am after?
非常感谢!
推荐答案
希望这对您仍然有用。
您可以通过定义reduceAdd来实现,针对您的特定用例的reduceRemove和reduceInitial函数,然后将它们传递给reduce。
You can do this by defining reduceAdd, reduceRemove and reduceInitial functions for your specific use case and then passing them to reduce.
代码:
var cf = crossfilter(data),
year = cf.dimension(function(d) { return d.year; });
var reduceAdd = function(p, v) {
p.tons_available += v.tons_available;
p.tons_sold += v.tons_sold;
p.str = p.tons_sold/p.tons_available;
return p;
}
var reduceRemove = function(p, v) {
p.tons_available -= v.tons_available;
p.tons_sold -= v.tons_sold;
p.str = p.tons_sold/p.tons_available;
return p;
}
var reduceInitial = function() {
return {
tons_available : 0,
tons_sold : 0,
str : 0
}
}
var json = year.group().reduce(reduceAdd,reduceRemove,reduceInitial).orderNatural().top(Infinity);
console.log(json);
Crossfilter添加记录时,它使用reduceAdd重新计算值。当Crossfilter删除筛选出的记录时,它将使用reduceRemove更新值。它需要一个由reduceInitial提供的初始值(请注意,这是一个函数)。请参阅文档。
When Crossfilter adds records it uses reduceAdd to recalculate values. When Crossfilter removes filters out records it uses reduceRemove to update values. It needs an initial value which is supplied by reduceInitial (note that it's a function). See this permalink from the docs https://github.com/square/crossfilter/wiki/API-Reference#group_reduce.
我使用了上面给出的输入,因此得到的是json:
I used the input that you gave above and this is the json that I got as a result:
[{key: "1988", value: {
str: 0.37404580152671757,
tons_available: 131,
tons_sold: 49},
{key: "1987", value: {
str: 0.6901408450704225,
tons_available: 71,
tons_sold: 49}]
这与您要求的输出不完全相同,但是非常接近。
It's not exactly the output you asked for, but it's pretty close.
这篇关于Crossfilter中的自定义计算的聚合字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!