简体   繁体   中英

Ordering a bar chart labels in dc.js (again)

I know there are a lot of questions on that specific subject on SO but none of the solutions seem to work in my case.

This is my data :

var theData = [{
  "value": "190.79",
  "age_days": "22",
  "criteria": "FX"
}, {
  "value": "18.43",
  "age_days": "22",
  "criteria": "FX"
}, {...}]

I put the data into buckets as such :

var getAge = (d) => {
  if ((d.age_days) <= 7) {
    return (["1w", "2w", "1m", "3m", "6m", "1y", "All"]);
  } else if ((d.age_days) <= 14) {
    return (["2w", "1m", "3m", "6m", "1y", "All"]);
  } else if ((d.age_days) <= 30) {
    return (["1m", "3m", "6m", "1y", "All"]);
  } else if ((d.age_days) <= 90) {
    return (["3m", "6m", "1y", "All"]);
  } else if ((d.age_days) <= 180) {
    return (["6m", "1y", "All"]);
  } else if ((d.age_days) <= 360) {
    return (["1y", "All"]);
  } else {
    return (["All"]);
  }
};

var ndx = crossfilter(theData);
var dims = {};
var groups = {};

dims.age = ndx.dimension(getAge,true);
groups.age = {};
groups.age.valueSum = dims.age.group().reduceSum((d) => d.value);

I then try to order the group using the fake group approach :

var sort_group = (source_group, order) => { 
    return {
        all: () => {
            let g = source_group.all();
            let map = {};
            g.forEach(function (kv) {
                map[kv.key] = kv.value;
            });
            return order
                .filter((k) => map.hasOwnProperty(k))
                .map((k) => {
                    return {key: k, value: map[k]}
                });
        }
    };
};
var the_order = ["1w", "2w", "1m", "3m", "6m", "1y", "All"];
var the_sorted_age_group = sort_group(groups.age.valueSum, the_order);

then I create the barChart using

theAgeChart
  .height(200)
  .width(400)
  .dimension(dims.age)
  .group(the_sorted_age_group)
  .valueAccessor((d) => d.value)
  .x(d3.scaleBand())
  .xUnits(dc.units.ordinal);

But it still comes out using the default sort :

在此处输入图片说明

I've created a jsFiddle here which contains everything.

How can I get my bars sorted as I want them to be sorted ?

When elasticX is true or the x scale domain is not set, the coordinate grid mixin will generate the X domain

        if (_chart.elasticX() || _x.domain().length === 0) {
            _x.domain(_chart._ordinalXDomain());
        }

(source)

That totally makes sense, but it always sorts the domain when it generates it:

_chart._ordinalXDomain = function () {
    var groups = _chart._computeOrderedGroups(_chart.data());
    return groups.map(_chart.keyAccessor());
};

(source)

I guess we could consider not sorting the domain when ordering is null.

Anyway, one workaround is to set the domain yourself:

.x(d3.scaleBand().domain(the_order))

You don't need to sort the group for a bar chart. (For a line chart, the group order must agree with the scale domain, but it doesn't matter for the bar chart.)

With the domain set, this also works:

.group(groups.age.valueSum)

正确排序的酒吧

Fork of your fiddle.

I guess the moral of the story is that it's complicated to generate charts automatically. Most of the time one does want the X domain sorted, but what's the best way to allow the user to provide their own sort?

I would not say this is the best way, but there is a way to make it work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM