Search code examples
dc.js

dc.js filter by row values


I have a dataset similar to below:

enter image description here

I would like to find total amount of "sea shipment" over "train shipment" and display it with dc.numberDisplay("#");

total sea shipment / total train shipment

Not sure if i need to use custom reduction.

so far i have used below code but it returns 1

   ndx = crossfilter(data);
   var all = ndx.groupAll();

var allGroup = all.reduce(
    function (p, v) {
             
        p.total += v.total;      
        p.sea = (v.shipment_type === "sea") ? 0 : p.total ;
        p.train = (v.shipment_type === "train") ? 0 : p.total ;
        p.air = (v.shipment_type === "air") ?0 : p.total ;

        p.sea_over_train = p.sea / p.train;
        return p;
    },
    function (p, v) {
        
        p.total -= v.total;     
        p.sea = (v.shipment_type === "sea") ? 0 : p.total ;
        p.train = (v.shipment_type === "train") ? 0 : p.total ;
        p.air = (v.shipment_type === "air") ?0 : p.total ;

        p.sea_over_train = p.sea / p.train;
        return p;
    },
    function () {
        return {                  
            total: 0,
            sea: 0,
            train :0,
            air:0,
            sea_over_train:0,

        };
    }
);

seaOverTrain
    .group(allGroup)
    .valueAccessor(function (x) { return x.sea_over_train; })
    .formatNumber(d3.format(".3s"));

Solution

  • I think you're on the right track but

    1. You may have your ?:s reversed
    2. You may need to take the total for each category, and
    3. Not use the overall total

    Let's take this line as an example:

        p.sea = (v.shipment_type === "sea") ? 0 : p.total ;
    

    This will set p.sea to 0 if the shipment_type is "sea", and will set it to p.total otherwise. You probably want this the other way around.

    Also, I think your intention is to keep a running total of sea, train, and air, so you could use += and -=, along with v.total, to do that.

    Currently these variables will take the overall total from p.total (which may be why you're getting 1... not sure...)

    Putting these ideas together we get:

    function (p, v) {
             
        p.total += v.total;      
        p.sea += (v.shipment_type === "sea") ? v.total : 0 ;
        p.train += (v.shipment_type === "train") ? v.total : 0 ;
        p.air += (v.shipment_type === "air") ? v.total : 0 ;
    
        p.sea_over_train = p.sea / p.train;
        return p;
    },
    function (p, v) {
        
        p.total -= v.total;     
        p.sea -= (v.shipment_type === "sea") ? v.total : 0 ;
        p.train -= (v.shipment_type === "train") ? v.total : 0 ;
        p.air -= (v.shipment_type === "air") ? v.total : 0 ;
    
        p.sea_over_train = p.sea / p.train;
        return p;
    },