Crossfilter: how to remove or filter values from group

vanessa picture vanessa · Feb 25, 2014 · Viewed 7.4k times · Source

I'm trying to get a group with the sum of values of a csv file, but I want to remove all the zero values.

Example of my csv file:

Continents      Function      Value  
South Asia      Function1   
South Asia      Function2     14  
Europe          Function1   
Europe          Function2     12  
Europe          Function3     2

I want to get

{"key":"Function2","value":26},  
{"key":"Function3","value":2}

Here is my code:

var ndx = crossfilter( csv );  
var functions = ndx.dimension( function( d )
{
   return d["Function"];
} );  
var functionAmountGroup = functions.group().reduceSum( function ( d )
{
   return d3.format( ".2f" )( d["Value"] );
} );

I get

{"key":"Function2","value":26},  
{"key":"Function3","value":2},  
{"key":"Function1","value":0}

but I want to remove the "Function1" line because of the zero value.

I tried to filter with the value dimension, it's ok

var filterValues = ndx.dimension( 
   function( d )
   {
      return d["Value"];
   } ).filter( 
       function( d )
       {
          if( 0 < Math.abs( d ) )
            return d;
       } );  

That returns me well :

{"Continents":"Europe","Function":"Function3","Value":"2"},  
{"Continents":"South Asia","Function":"Function2","Value":"14"},
{"Continents":"Europe","Function":"Function2","Value":"12"}

But filterValues is now a dimension, then I don't know how to get a new dimension with "Function" with these filtered result.
Something like

filteredValues.dimension( function( d )
        {
            return d["Function"];
        } );  

which is wrong!

Can someone help me please? I have no more ideas!
Thanks a lot,
vanessa

Answer

Ethan Jewett picture Ethan Jewett · Feb 25, 2014

Please create a jsFiddle. I don't believe the code you post does what you say it does, and a working example will solve this problem. Specifically:

var filterValues = ndx.dimension( 
   function( d )
   {
      return d["Value"];
   } ).filter( 
       function( d )
       {
          if( 0 < Math.abs( d ) )
            return d;
       } );  

returns a dimension, not a list of records.

To answer your question: If you do the following, functionAmountGroup.top(Infinity) should give you what you want.

var ndx = crossfilter( csv );  
var functions = ndx.dimension( function( d ) {
   return d["Function"];
} );  
var functionAmountGroup = functions.group().reduceSum( function ( d ) {
   return d3.format( ".2f" )( d["Value"] );
} );
var filterValues = ndx.dimension( 
   function( d ) {
      return d["Value"];
   } ).filter( 
       function( d ) {
          if( 0 < Math.abs( d ) )
            return d;
       } );

The .filter() call on the new dimension will adjust the functionAmountGroup defined on the other dimension.

You could also just do:

var ndx = crossfilter( csv );  
var functions = ndx.dimension( function( d ) {
   return d["Function"];
} );  
var functionAmountGroup = functions.group().reduceSum( function ( d ) {
   return d3.format( ".2f" )( d["Value"] );
} );
functionAmountGroup.top(Infinity).filter( function (d) { return d.value !== 0; } );

Edit: This doesn't work. You actually need to create a fake Crossfilter group that is pre-filtered and pass it to dc.js. Like this:

var filteredFunctionAmountGroup = {
    all: function () {
        return functionAmountGroup.top(Infinity).filter( function (d) { return d.value !== 0; } );
    }
}

Example here: http://jsfiddle.net/h28hp/17/