我使用dc.js和Crossfilter面临一个奇怪的问题。想象一下以下数据和代码
test_data = [{date: d3.time.format("%Y-%m-%dT%H:%M:%S+0100").parse("2014-11-24T12:00:00+0100"), cnt: 1},
{date: d3.time.format("%Y-%m-%dT%H:%M:%S+0100").parse("2014-11-24T11:00:00+0100"), cnt: 2},
{date: d3.time.format("%Y-%m-%dT%H:%M:%S+0100").parse("2014-11-24T12:00:00+0100"), cnt: 3}],
test_ndx = crossfilter(test_data),
test_dim = test_ndx.dimension(function(d) { return d.date; }),
test_grp = test_dim.group(function(d) { return d.getHours(); });
test_grp.all()
按照我的预期返回[{key: 11, value: 1}, {key: 12, value: 2}]
。
如果我将最后一行更改为
test_grp = test_dim.group(function(d) { return -d.getHours(); });
test_grp.all()
返回[{key: -11, value: 3}]
。
为什么不返回[{key: -11, value: 1}, {key: -12, value: 2}]
?
答案 0 :(得分:5)
我不认为这是crossfilter中的一个问题;我认为你违反了crossfilter API,它指出:
与值函数一样, groupValue 必须返回一个自然排序的值;此外,此订单必须与维度值功能一致!
https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_group
由于减号, groupValue 函数返回的值的顺序将反转为尺寸值函数值的顺序。
我过度简化了,但在下面,crossfilter组试图保持bin的索引的顺序与维度具有自己的所有值索引的顺序相同。如果组的索引中的值无序,则无法正确确定bin边界。这些简单的假设是使crossfilter如此之快的部分原因。
这是一个更简单的示例,不使用具有相同行为的日期:
test_data = [{date: 12, cnt: 1},
{date: 11, cnt: 2},
{date: 12, cnt: 3}],
test_ndx = crossfilter(test_data),
test_dim = test_ndx.dimension(function(d) { return d.date; }),
test_grp = test_dim.group(function(d) { return -d; });
此test_grp
还包含[{"key":-11,"value":3}]
实际上,任何date.getAnything()
函数通常都不会在组值函数中使用(具有维值函数的日期),除非观察恰好跨越了Anything。
例如,假设您使用date.getMonth()
- 如果所有日期都是从一个月开始,那么您就可以了,因为维度的排序与群组相匹配。但是如果日期是3月29日,3月31日,4月1日,4月2日,则crossfilter可以决定它可以在3月29日结束时创建一个组边界,并将最后三个日期粘贴在第二个bin中,或者在4月1日结束,前三个日期。
同样,我简化了,这不是crossfilter的功能。但是它的算法依赖于<
和<=
以相同的方式处理维度值和组值。如果这不是真的,它就不会检测到问题(因为这会很慢) - 它会默默地创建错误的聚合。
正如NaN
由于订单排序不正常而导致的常见投诉一样,在crossfilter之上还有验证库的空间。但是你仍然需要根据它的假设设置交叉滤波器,这使得它的效率非常高。