我在根据针对一个字段的值完成的计算对样本进行分组时遇到问题。样品采用
的形式
{
"dataset": "DATASET2",
"sampleid": "ID2653",
"variables": {
// several variables, key: val
},
"bmus": {
"x": 3,
"y": 7
}
}

样本属于静态9x7网格中的单元格,bmus字段映射网格中样本的位置。圆形滤镜可以在网格顶部移动,移动圆形滤镜后,我希望能够将位于圆圈内的样本组合在一起。分组将采用
的形式
{
"key": {
"circles": ["circle1", "circle2"] // or [], ['circle1'], ['circle2']
},
"value": 282
}

之后,将根据某些变量的值计算自定义缩减函数。
我目前创建维度和分组的设置如下:
$scope.dimension = crossfilterInst.dimension( function(d) {
return {
bmu: d.bmus,
valueOf: function() {
var ret = _.isUndefined(d.bmus) ? String(constants.nanValue) + "|" + String(constants.nanValue) : d.bmus.x + "|" + d.bmus.y;
// for NaN's the result is "-100|-100", otherwise in the form of "5|4"
return ret;
}
};
});
var group = $scope.dimension.group( function(d) {
return {
circles: function() {
return FilterService.inWhatCircles(d.bmu);
},
valueOf: function() {
return String(this.circles());
}
};
});

首先,group.all()
的分组是正确的。之后,当在网格上移动圆形滤镜时,通过将filterFunction
应用于crossfilterInst
的另一个维度,从而影响FilterService.inWhatCircles()
的返回值,从而影响所选的样本数量,从group.all()
返回的组的样本数量越来越不正确。
最初我认为FilterService.inWhatCircles()
的返回值在某些情况下是不正确的。经过长时间的调试后,我注意到如果我重新创建维度(处理旧维度+运行创建$scope.dimension
的相同代码),然后使用相同的代码对样本进行分组,结果组是正确的。
看看Crossfilter API,我怀疑crossfilter做了一些缓存,搞砸了我的分组,或者这个要求不满足:
与value函数一样,groupValue必须返回一个自然排序的 值;此外,此顺序必须与尺寸一致 价值功能!
长话短说:如何根据样本的FilterService.inWhatCircles()
字段计算bmus
,并在函数返回值发生变化时重复将它们组合在一起,而不必每次重新创建维度以获得正确的组?
答案 0 :(得分:1)
您猜对了:crossfilter正在以不允许您使用动态计算任何内容的组或维度过滤器的方式索引数据。密钥必须已存在于数据中且无法更改。它们只会被阅读一次。
您的组密钥与维度密钥不一致的事实是您遇到的问题最少。
相反,您可能希望使用fake group,一个带有.all()
方法的对象循环遍历所有数据点,并计算与每个inWhatCircles
值匹配的数字,例如通过使用地图。然后它应该返回group.all
返回的{key,value}对的相同类型的数组。
这比每次创建一个新维度及其所有索引更有效,并且您不会失去交叉过滤器的大部分好处,因为它无论如何都没有针对这种动态计算进行优化。