1
votes

My issue here is that I have a crossfilter group reduce function for calculating savings, but when a filter is applied on a chart, it seems to not pass the correct filter across. I also have a similar case working example.

I have created two jsbin's out of which one of them has correct behavior.

I have data for two years in this case 2010 and 2014. But in the Savings(not working) chart the carrier pie chart doesn't filter by year whereas it does in the DIFOT(working) chart.

The links are : DIFOT(Working) : http://jsbin.com/bagohavehu/2/edit Savings (Not working as expected) : http://jsbin.com/yudametulo/2/edit

Thanks a lot for your time and effort.

Regards, Animesh

1
I don't understand. They appear to both filter for me. JS Bin quibbled about some semi-colons, here is DIFOT jsbin.com/reyecutaqi/1/edit and Savings jsbin.com/nodibaraji/1/editGordon
Hello Gordon thanks for your swift reply, the issue I am facing in particular is about filtering the right values. For both the chart sets I am using the same data therefore I only have one record for year 2010 and carrier 1117. But in the case of savings all the carrier's are shown when year 2010 is selected in the year pie chart. Whereas DIFOT carrier chart gets the right year filter and thus displays the data for that particular year. Thanks.Animesh
Also on further investigation I figured out that if I parse my current and comparePrice as int's rather than floats(which I am doing right now) the savings charts filter by year have expected behavior. Hope this helps. ThanksAnimesh
I'm not sure what you're calculating, but since your reduce function does not take the count into account, that is why it will ignore whether they are filtered in or not. As an example, here is a fork of your example (as a jsfiddle: easier to debug) with the count multiplied into the result - not sure if that makes sense for your calculation but it reflects the filter better: jsfiddle.net/gordonwoodhull/9f6kzeus/11Gordon
Thanks a lot Gordon. I was using count for just debugging purposes, I will post a bin without count in the reduce function. The link for the bin is jsbin.com/tehulisipu/2/edit. If you change the parseFloat to parseInt in the reduce function you will get the filtering working properly. Hope this information makes sense. Thanks.Animesh

1 Answers

2
votes

To track these calculation problems down, you really need to use the debugger and put breakpoints in the reduction functions or in the draw functions to see what reduced values you ended up with.

I find using the browser's debugger very difficult (impossible?) to do in jsbin, so I have again pasted your code into two jsfiddles:

parseFloat version: http://jsfiddle.net/gordonwoodhull/aqhLv0qc/

parseInt version: http://jsfiddle.net/gordonwoodhull/9bnejpLx/1/

Now, we set a breakpoint in chart.redraw (dc.js:1139) to see what values it's trying to plot on clicking the slice.

The first time the breakpoint is hit isn't interesting, because it's just the yearly chart we clicked on, but the second hit is the carrier chart, which reveals a lot. Printing _chart.group().all() for the parseInt version:

parseInt group bin values

Now, for the parseFloat version:

enter image description here

Since the calculations come out exact for the int version, you end up with 1 - 0/0 === NaN, and somewhere along the way dc.js or d3.js silently forces NaN to zero.

But since float calculations are never exact, you end up with 1 - 0/-3e-15 === 1.

You want to avoid dividing by zero, or anything close to zero, so adding a check in your reduction function produces (I think) the desired result:

var group = Dim.group().reduce(
    function(p,v){
        p.current += parseFloat(v.currentPrice);
        p.compare += parseFloat(v.comparePrice);
        if(Math.abs(p.compare) > 0.01) {
            p.savings  = p.current/p.compare;
            p.result   = 1-p.savings;
        }
        else p.result = 0;
        return p;
    },
    function(p,v){
        p.current -= parseFloat(v.currentPrice);
        p.compare -= parseFloat(v.comparePrice);
        if(Math.abs(p.compare) > 0.01) {
            p.savings  = p.current/p.compare;
            p.result   = 1-p.savings;
        }
        else p.result = 0;
        return p;
    },
    function(){return { current: 0, compare: 0,savings:0, result:0};}
);

Working version (I think): http://jsfiddle.net/gordonwoodhull/y2sf7y18/1/