Search code examples
dc.jscrossfilter

Crossfilter and DC.js: reduce to unique number


In the example below, I am trying to sum by unique occurence of Respond_Id. eg. in this case, it should be in total 3, "Respond_Id" being 258,261 and 345.

This is my data:

{"Respond_Id":258,"Gender":"Female","Age":"18-21","Answer":424},
{"Respond_Id":258,"Gender":"Female","Age":"18-21","Answer":428},
{"Respond_Id":261,"Gender":"Male","Age":"22-26", "Answer":427},
{"Respond_Id":261,"Gender":"Male","Age":"22-26",  "Answer":432},
{"Respond_Id":345,"Gender":"Female","Age":"27-30","Answer":424},
{"Respond_Id":345,"Gender":"Female","Age":"27-30","Answer":425},
{"Respond_Id":345,"Gender":"Female","Age":"27-30","Answer":433},

I know I should use group reduce for this, so I tried (adapted from an example):

var ntotal =  answerDim.group().reduce(
                function(p, d) { 
                    if(d.Respond_Id in p.Respond_Ids){
                        p.Respond_Ids[d.Respond_Id]++;
                    }
                    else {
                        p.Respond_Ids[d.Respond_Id] = 1;
                        p.RespondCount++;
                    }
                    return p;
                },
                function (p, d) {
                    p.Respond_Ids[d.Respond_Id]--;
                    if(p.Respond_Ids[d.Respond_Id] === 0){
                        delete p.Respond_Ids[d.Respond_Id];
                        p.RespondCount--;
                    }
                    return p;
                },
                function () {
                    return {
                        RespondCount: 0,
                        Respond_Ids: {}
                    };

                }
            );

Then:

numberDisplay
         .group(ntotal)
         .valueAccessor(function(d){ return d.value.RespondCount; });

     dc.renderAll();

But seems not working. Does someone know how to make it work ? Thank you


Solution

  • Based on your JSFiddle, your setup is like this:

    var RespondDim       =  ndx.dimension(function (d) { return d.Respond_Id;});
    var ntotal           =  RespondDim.group().reduce(
                                    function(p, d) { 
                                        if(d.Respond_Id in p.Respond_Ids){
                                            p.Respond_Ids[d.Respond_Id]++;
                                        }
                                        else {
                                            p.Respond_Ids[d.Respond_Id] = 1;
                                            p.RespondCount++;
                                        }
                                        return p;
                                    },
                                    function (p, d) {
                                        p.Respond_Ids[d.Respond_Id]--;
                                        if(p.Respond_Ids[d.Respond_Id] === 0){
                                            delete p.Respond_Ids[d.Respond_Id];
                                            p.RespondCount--;
                                        }
                                        return p;
                                    },
                                    function () {
                                        return {
                                            RespondCount: 0,
                                            Respond_Ids: {}
                                        };
                                     });
    

    What is important to note here is that your group keys, by default, are the same as your dimension keys. So you will have one group per respondent ID. This isn't what you want.

    You could switch to using dimension.groupAll, which is designed for this use case, but unfortunately the dimension.groupAll.reduce signature is slightly different. The easiest fix for you is going to be to just define your dimension to have a single value:

    var RespondDim       =  ndx.dimension(function (d) { return true;});
    

    Now you'll see that ntotal.all() will look like this:

    {key: true, value: {RespondCount: 3, Respond_Ids: {258: 2, 261: 2, 345: 3}}}
    

    Working fiddle: https://jsfiddle.net/v0rdoyrt/2/