Search code examples
d3.jsdc.jscrossfilter

Crossfilter dimension filtering


I'm working on dc.js charts. I have setup the fiddle here.

I have the data below:

var data = [
  {"state": "A","value": 100,"volume": 10,"id": 4,"date": "10/1/2017","category": "H","channel": "CRM"},
  {"state": "B","value": 50,"volume": 10,"id": 2,"date": "8/1/2017","category": "A","channel": "CRM"},
  {"state": "A","value": 250,"volume": 5,"id": 4,"date": "10/1/2017","category": "H","channel": "CRM"},
  {"state": "A","value": 40,"volume": 4,"id": 3,"date": "9/1/2017","category": "A","channel": "Sales"},
  {"state": "C","value": 10,"volume": 1,"id": 5,"date": "11/1/2017","category": "A","channel": "Sales"},
  {"state": "B","value": 10,"volume": 1,"id": 2,"date": "8/1/2017","category": "H","channel": "CRM"},
  {"state": "D","value": 150,"volume": 3,"id": 1,"date": "7/1/2017","category": "A","channel": "Sales"},
  {"state": "D","value": 100,"volume": 5,"id": 1,"date": "7/1/2017","category": "H","channel": "Sales"},
  {"state": "C","value": 50,"volume": 1,"id": 5,"date": "11/1/2017","category": "H","channel": "Sales"}
]

I have four dimensions (state, category, channel, id) and all are grouped by value.

I need to know if I can filter the dimension such that if I set the range 60, the charts should show all the ids whose value total is greater than 60.

For example it the states pie chart should show only the slices where the value is greater than 60, i.e. A and D only.


Solution

  • By itself, crossfilter won't filter by value. If you think about it, it would be pretty complicated to filter the data set by the rows by the ones that will reduce to a certain value, before it's done the reduction.

    But I think you're not looking for filtering so much as just not showing the slices that are too small. You can do that using a "fake group". This is a postprocessing step which won't change what data is included in the crossfilter filters, just what items you choose to display.

    This one is very similar to the "remove empty bins" fake group. But instead of looking for the value 0, we'll look for a minimum value.

    function remove_small_bins(source_group, lower_bound) {
        return {
            all:function () {
                return source_group.all().filter(function(d) {
                    return d.value > lower_bound;
                });
            }
        };
    }
    

    Applying it to your example (the fiddle data is slightly different from the data shown above), first we need to look at d.value.orderValue instead of justd.value`:

    function remove_small_bins(source_group, lower_bound) {
        return {
            all:function () {
                return source_group.all().filter(function(d) {
                    return d.value.orderValue > lower_bound;
                });
            }
        };
    }
    

    Apply the fake group like this:

    var stateGroup = stateDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);
    var stateGroupNoSmalls = remove_small_bins(stateGroup, 60);
    // ...
    stateChart
      .group(stateGroupNoSmalls)
    

    Fork of your fiddle: https://jsfiddle.net/gordonwoodhull/cyjztajv/2/