Roger A. Leite
Roger A. Leite

Reputation: 396

How to use top function in a group created with a custom reduction?

in the scenario presented in: http://jsfiddle.net/rogeraleite/xbd0zpzn/6/

1 - I would like to display bars from the top 2 names according to the sum of theirs amount values.

2 - It is also important to keep the multi-color feature(red/teal). This is identifying the "approved_flag".

Expected result: I should be showing Mike and Firen as the top 2 names.

I guess that because the .value is appearing as an Object[amount,unapproved], the top function is not calculating the right ranking.

Based on that, I was already thinking in change the d.value = d.value.amount temporally in order to make the function top(2) works based on the d.value.amount. However, I could not do that. I not so sure if it would be the right way as well.

code I am using:

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

var nameDimension = ndx.dimension(function (d) { return d.Name; });

var nameGroup = nameDimension.group().reduce(
    function (p, v) { // add
        p.amount += v.amount
        if(!v.approved_flag)
            p.unapproved++;
        return p;
    },
    function (p, v) { // remove
        p.amount -= v.amount
        if(!v.approved_flag)
            p.unapproved--;
        return p;
    },
    function () { // initialize
        return {amount: 0, unapproved: 0};
    }
);

var filterNameGroup = (function(source_group){return{
    all:function(){
    return source_group.top(2).filter(function(d){
        return d.key != "Not mentioned";
    });
  }
}
})(nameGroup)

var chart1 = dc.barChart('#barChart1');
var chart2 = dc.rowChart('#rowChart1')

chart1.width(600)
    .height(250)
    .margins({ top: 10, right: 10, bottom: 20, left: 40 })
    .dimension(nameDimension)
        .group(nameGroup)
    .transitionDuration(500)
        .colors(function(x) { return x; })
    .elasticY(false)
    .brushOn(false)
    .valueAccessor(function (d) {
        return d.value.amount;
    })
    .title(function (d) {
        return "\nNumber of Povetry: " + d.key;
    })
    .colorAccessor(function(d) {
        return (!this.name && d.value.unapproved) ? 'red' : 'teal';
    })
  .x(d3.scale.ordinal().domain(nameDimension.top(Infinity).map(function(d) {return d.Name})))
    .xUnits(dc.units.ordinal)
    .legend(dc.legend().x(45).y(20).itemHeight(8).gap(4))
;


chart2.width(600)
    .height(250)
    .margins({ top: 10, right: 10, bottom: 20, left: 40 })
        .group(filterNameGroup)
    .dimension(nameDimension)
        .colors(function(x) { return x; })
    .valueAccessor(function (d) {
        return d.value.amount;
    })
    .colorAccessor(function(d) {
        return (!this.name && d.value.unapproved) ? 'red' : 'teal';
    })
        .ordering(function(d){return -d.value});


dc.renderAll();

I hope you can help me.

Thanks in advance, Roger A L.

Upvotes: 0

Views: 43

Answers (1)

Ethan Jewett
Ethan Jewett

Reputation: 6010

I think you just need to define an order on your nameGroup so that Crossfilter knows how to order the groups - https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_order

nameGroup.order(function(d) { return d.amount; });

Upvotes: 1

Related Questions