【问题标题】:Apply Filter from one Crossfilter dataset to another Crossfilter将过滤器从一个 Crossfilter 数据集应用到另一个 Crossfilter
【发布时间】:2014-08-05 04:42:44
【问题描述】:

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

例如:

数据集 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
...

Dataset 1 有自己的 crossfilter 对象,Dataset 2 有一个单独的 crossfilter 对象。我有多个 dc.js 图表,一些与数据集 1 相关联,一些与数据集 2 相关。

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

【问题讨论】:

    标签: d3.js dc.js crossfilter


    【解决方案1】:

    我认为在 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))
        // ...
    

    由于所有图表都是implicitly on the same chart group,因此重绘事件在过滤时将自动在它们之间传播。并且一个交叉过滤器上的每个过滤器操作都将应用于另一个交叉过滤器上的镜像维度。

    也许不是我推荐做的事情,但像往常一样,它可以工作。

    这是小提琴:https://jsfiddle.net/gordonwoodhull/7dwn4y87/8/

    【讨论】:

    • 我有同样的情况,有两个数据集进行比较。如果我单击数据集 1 中的一项,它将在数据集 2 图表中反映相同。你能建议我一个更好的方法来处理这个问题吗?
    • 这是我所知道的最好的方法,除了@Ethan 建议将数据组合到一个交叉过滤器中(这样它就变成了数据问题而不是逻辑问题)。你试过这个吗?它是如何失败的?
    • jsfiddle.net/caravinden/y8tts7eo@Gordon 在这个例子中,我如何同步两个图之间的点击事件?
    • 好的,我已经在上面创建了一个完整的示例。这可能会导致更多的混乱和困难,但确实如此。
    • 非常感谢..你让我开心..:d
    【解决方案2】:

    @Gordon 的建议不错。

    我通常以不同的方式处理此问题,将 2 个表合并到一个表中(将 ValueA 和 ValueB 添加到数据集 1 的每一行),然后使用自定义分组为每个唯一的年份/类别仅聚合一次 ValueA 和 Value B组合。每个组都需要保留之前看到的键的映射以及每个键的计数,如果它是键的新组合,则仅聚合 ValueA 或 ValueB 的值。这确实会导致复杂的分组逻辑,但可以避免需要在 2 个 Crossfilter 对象之间进行协调。

    就我个人而言,我只是发现复杂的自定义分组比协调逻辑更容易测试和维护,但并不是每个人都这样。

    【讨论】:

      猜你喜欢
      • 2014-08-02
      • 1970-01-01
      • 2015-11-15
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多