D3.js 将筛选器从一个交叉筛选器数据集应用到另一个交叉筛选器

D3.js 将筛选器从一个交叉筛选器数据集应用到另一个交叉筛选器,d3.js,dc.js,crossfilter,D3.js,Dc.js,Crossfilter,我有两个数据集,它们具有相似的列/维度,但按行分组不同,并且包含不同的度量值 例: 数据集1 Year Category SubCategory Value01 Value02 2000 Cars Sport 10 11 2000 Cars Family 15 16 2000 Boats Sport 20 21 2000 Boa

我有两个数据集,它们具有相似的列/维度,但按行分组不同,并且包含不同的度量值

例:

数据集1

Year   Category   SubCategory    Value01    Value02
2000   Cars       Sport          10         11
2000   Cars       Family         15         16
2000   Boats      Sport          20         21
2000   Boats      Family         25         26
...
数据集2

Year   Category    ValueA     ValueB
2000   Cars        100        101
2000   Boats       200        201
...
数据集1有自己的交叉过滤器对象,数据集2有单独的交叉过滤器对象。我有多个dc.js图表,一些与数据集1关联,一些与数据集2关联


当dc.js图表在数据集2中也存在的列/维度上过滤数据集1时,我希望将相同的过滤器应用于数据集2。如何实现这一点?

我认为在crossfilter或dc.js中没有任何自动方法可以做到这一点。但是,如果您愿意滚动自己的维度包装器,您可以提供它而不是原始维度对象,并将其转发到所有底层维度

编辑:根据下面@Aravind的小提琴,这里有一个“维度镜像”,至少在这个简单的例子中是有效的:

function mirror_dimension() {
    var dims = Array.prototype.slice.call(arguments, 0);
    function mirror(fname) {
        return function(v) {
            dims.forEach(function(dim) {
                dim[fname](v);
            });
        };
    }
    return {
        filter: mirror('filter'),
        filterExact: mirror('filterExact'),
        filterRange: mirror('filterRange'),
        filterFunction: mirror('filterFunction')
    };
}
用这个有点乱。对于要从交叉过滤器A镜像到交叉过滤器B的每个维度,需要在交叉过滤器B上创建镜像维度,反之亦然:

// Creating the dimensions
subject_DA = CFA.dimension(function(d){ return d.Subject; });
name_DA = CFA.dimension(function(d){ return d.Name; });
// mirror dimensions to receive events from crossfilter B
mirror_subject_DA = CFA.dimension(function(d){ return d.Subject; });
mirror_name_DA = CFA.dimension(function(d){ return d.Name; });

subject_DB = CFB.dimension(function(d){ return d.Subject; });
name_DB = CFB.dimension(function(d){ return d.Name; });
// mirror dimensions to receive events from crossfilter A
mirror_subject_DB = CFB.dimension(function(d){ return d.Subject; });
mirror_name_DB = CFB.dimension(function(d){ return d.Name; });
现在,在将它们传递到图表时,将它们绑定在一起:

// subject Chart
subjectAChart
    .dimension(mirror_dimension(subject_DA, mirror_subject_DB))
    // ...

// subject Chart
subjectBChart
    .dimension(mirror_dimension(subject_DB, mirror_subject_DA))
    // ...

nameAChart
    .dimension(mirror_dimension(name_DA, mirror_name_DB))
    // ...

nameBChart
    .dimension(mirror_dimension(name_DB, mirror_name_DA))
    // ...
由于所有图表都是相同的,因此在过滤它们时,重绘事件将自动在它们之间传播。一个交叉过滤器上的每个过滤器操作将应用于另一个交叉过滤器上的镜像维度

也许我不建议你这么做,但像往常一样,它可以发挥作用


问题是:

@Gordon的建议很好

我通常采用不同的方法,将这两个表合并到一个表中(将ValueA和ValueB添加到数据集1的每一行),然后使用自定义分组仅为每个独特的年份/类别组合聚合ValueA和ValueB一次。每个组都需要保留一个它以前看到的键的映射以及每个键的计数,如果它是一个新的键组合,则只聚合ValueA或ValueB的值。这确实会导致复杂的分组逻辑,但允许您避免需要在两个交叉过滤器对象之间进行协调


就我个人而言,我只是觉得复杂的自定义分组比协调逻辑更容易测试和维护,但并非每个人都是如此。

我有两个数据集进行比较。如果我点击数据集1中的一个项目,它将在数据集2图表中反映相同的内容。请你给我一个更好的方法来处理这个问题。这是我所知道的最好的方法,除了@Ethan建议将数据合并到一个交叉过滤器中(这样它就变成了一个数据问题而不是逻辑问题)。你试过这个吗?它是怎么失败的@Gordon在本例中,如何在两个图形之间同步单击事件?好的,我已经创建了上面的完整示例。这可能会导致更多的混乱和困难,但事实就是这样。非常感谢。。你让我开心