Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply Filter from one Crossfilter dataset to another Crossfilter

I have two datasets that have similar columns/dimensions but are grouped differently by row and contain different measures.

Ex:

Dataset 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
...

Dataset 2

Year   Category    ValueA     ValueB
2000   Cars        100        101
2000   Boats       200        201
...

Dataset 1 has its own crossfilter object, Dataset 2 has a separate crossfilter object. I have multiple dc.js charts, some tied to the dataset 1, some to dataset 2.

When a dc.js chart filters dataset 1 on a column/dimension that also exists in dataset 2, I want to apply that same filter to dataset 2. How can this be achieved?

like image 275
Aaron Hoffman Avatar asked Mar 19 '23 08:03

Aaron Hoffman


1 Answers

I don't think there is any automatic way to do this in crossfilter or dc.js. But if you're willing to roll your own dimension wrapper, you could supply that instead of the original dimension objects and have that forward to all the underlying dimensions.

EDIT: based on @Aravind's fiddle below, here is a "dimension mirror" that works, at least for this simple example:

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')
    };
}

It's a bit messy using this. For each dimension you want to mirror from crossfilter A to crossfilter B, you'll need to create a mirror dimension on crossfilter B, and vice versa:

// 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; });

Now you tie them together when passing them off to the charts:

// 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))
    // ...

Since all the charts are implicitly on the same chart group, the redraw events will automatically get propagated between them when they are filtered. And each filter action on one crossfilter will get applied to the mirror dimension on the other crossfilter.

Maybe not something I'd recommend doing, but as usual, it can be made to work.

Here's the fiddle: https://jsfiddle.net/gordonwoodhull/7dwn4y87/8/

like image 63
Gordon Avatar answered Apr 28 '23 13:04

Gordon