Pygirl
Pygirl

Reputation: 13349

Dc.js : Not able to order my bar graph using ordering

Line no. 85 of index.js.

Ordering function is not working since I ain't to get the output for console.log(). I don't know why it's not working for this case. For my rowChart I was able to sort by descending order using .ordering()

Here is the demo with code: https://blockbuilder.org/ninjakx/483fd69328694c6b6125bb43b9f7f8a7

I want these graphs to be sorted by values but unable to do it.

enter image description here

Update:

following this answer I came up with this solution (tried on a dummy case). But this only works when I use reduceCount(), reduceSum() function that is without reductio.js

I am using reductio.js to get the maximum value from the group.

       var data = crossfilter([
        { foo: 'one', bar: 1 },
        { foo: 'two', bar: 2 },
        { foo: 'three', bar: 3 },
        { foo: 'one', bar: 4 },
        { foo: 'one', bar: 5 },
        { foo: 'two', bar: 6 },
      ]);

      var dim = data.dimension(function(d) { return d.foo; });
      var group = dim.group();
      let TypeGroup = group.reduceCount(function(d) { 
          return d.bar; }
          );


      TypeGroup.order(function(p) {
          return p;
      });

      TypeGroup.all = function() {
          return group.top(Infinity);
      }

        focus = new dc.barChart('#focus');
// 
      focus
          // .ordering(function(d){return -d.value.max})
          //dimensions
          //.width(768)
          .height(250)
          .margins({top: 10, right: 50, bottom: 25, left: 50})
          //x-axis
          .x(d3.scaleOrdinal())
          .xUnits(dc.units.ordinal)
          .xAxisLabel('Department')
          //left y-axis
          .yAxisLabel('Sales')
          .elasticY(true)
          .renderHorizontalGridLines(true)
          //composition
          .dimension(dim)
          .group(TypeGroup)

      focus.ordering(function(d){
          return -d
      }); 

Output: enter image description here

For reductio:

       var data = crossfilter([
        { foo: 'one', bar: 1 },
        { foo: 'two', bar: 2 },
        { foo: 'three', bar: 3 },
        { foo: 'one', bar: 4 },
        { foo: 'one', bar: 5 },
        { foo: 'two', bar: 6 },
      ]);

      var dim = data.dimension(function(d) { return d.foo; });
      var group = dim.group();
      // let TypeGroup = group.reduceCount(function(d) { 
      //     return d.bar; }
      //     );

      var reducer_g = reductio().max(function(d) { 
          // console.log("max:",d.Time_estimate);
          return parseFloat(d.bar)
      });

      let TypeGroup = reducer_g(group);


      TypeGroup.order(function(p) {
        console.log(p);
          return p.max;
      });

      TypeGroup.all = function() {
          return group.top(Infinity);
      }

        focus = new dc.barChart('#focus');
// 
      focus
          // .ordering(function(d){return -d.value.max})
          //dimensions
          //.width(768)
          .height(250)
          .margins({top: 10, right: 50, bottom: 25, left: 50})
          //x-axis
          .x(d3.scaleOrdinal())
          .xUnits(dc.units.ordinal)
          .xAxisLabel('Department')
          //left y-axis
          .yAxisLabel('Sales')
          .elasticY(true)
          .renderHorizontalGridLines(true)
          //composition
          .dimension(dim)
          .group(TypeGroup)

      focus.ordering(function(d){
          return -d.value.max
      }); 

Output:

enter image description here

So you can see I ain't getting any bars. So I assume I am very close to the solution as I ain't getting any error in console. I believe if I made it work for this case then I will be able to sort the original graphs using the same.

Upvotes: 1

Views: 137

Answers (1)

Gordon
Gordon

Reputation: 20120

To summarize your question, you want an ordinal range/focus bar chart with bars sorted in descending order. To make things even more interesting, the groups are reduced using reductio.max.

I think the idea of overriding .all() to call .top() using the group's order is a false lead (although it could probably be made to work).

In the ordinal focus/range chart example which you use in your bl.ock (thank you!), we map the ordinal keys, in order, to integers on a linear scale.

It's easy to sort the values before doing the mapping, and it looks like the ordinal_to_linear_group function anticipated the need by taking sort as the second parameter. However it wasn't implemented, so let's add it!

function ordinal_to_linear_group(group, sort) {
    var _ord2int, _int2ord;
    return {
        all: function() {
            var ret = group.all();
            if(sort) // NEW
              ret = ret.slice().sort(sort);
            _ord2int = {};
            _int2ord = [];
            ret.forEach(function(d, i) {
                _ord2int[d.key] = i;
                _int2ord[i] = d.key;
            });
            return ret;
        },
        ord2int: function(o) {
            if(!_ord2int)
                this.all();
            return _ord2int[o];
        },
        int2ord: function(i) {
            if(!_int2ord)
                this.all();
            return _int2ord[i];
        }
    };
}

We need to slice off a copy, then sort it, because group.all() is returning its internal state and it gets confused if you change that array.

It takes a standard Array.sort comparator function, which we can supply using d3.descending:

     var group = ordinal_to_linear_group(barTypeGroup,
                    (a,b) => d3.descending(a.value.max, b.value.max));

descending ordinal range focus

Fork of your bl.ock.

Upvotes: 1

Related Questions