ZFlyGuy
ZFlyGuy

Reputation: 99

How can I apply a custom (defined) order to the rows of a row chart in DC.js?

I have a rowchart that currently looks like this:

deltaChart
    .width(300)
    .height(250)
    .dimension(deltaDim)
    .group(pointsByDelta)
    .xAxis().ticks(4);

In which the deltaDim dimension is comprised of 11 or so unique string values, pointsByDelta represents related counts, and deltaChart is of type rowChart.

Since the deltaDim values are string and not numeric, the sorting is out of order. I've tried applying what I've found in the wiki as well as on other's posts here to manually reorder, with no luck at all. Regardless of the format I receive a console error: .ordering is not a function()

I've tried just simple ordering like this:

.ordering(function(d){return -d.value})

That results in error. Ideally I'd like to be able to do something like:

.ordering(function(d) {
        if(d.value == "5 ft") return 0;
        else if(d.value == "4 ft") return 1;
        else if(d.value == "3 ft") return 2;
        else if(d.value == "2 ft") return 3;
        else if(d.value == "1 ft") return 4;
        else if(d.value == "0 ft") return 5;
        else if(d.value == "-1 ft") return 6;
        else if(d.value == "-2 ft") return 7;
        else if(d.value == "-3 ft") return 8;
        else if(d.value == "-4 ft") return 9;
        else if(d.value == "-5 ft") return 10;
        else return 11;
    })

It looks like most of the posts on this topic are responded to with a way to sort in ascending or descending order. I've not even been able to get that to behave, and in my case, I need to be able to dictate the order if possible.

Any help appreciated. Thank you!

Upvotes: 1

Views: 814

Answers (4)

Aravind Cheekkallur
Aravind Cheekkallur

Reputation: 3205

Better to avoid the lengthy if else condition. This can be easily handled through d3 scales

  1. Create the ordinal scale and domain with the preferred order.
  2. Range can be done with the index by sorting order

    var scale = d3.scale.ordinal()
    .domain(['C','B','A'])
    .range([0,1,2]);
    

    In ordering function

    chart.ordering(function(k){
      return scale(k.key);
    })
    

jsFiddle Working copy

Upvotes: 1

ZFlyGuy
ZFlyGuy

Reputation: 99

Combined with Gordon's input from above regarding .xAxis(), the solution that works is as follows.

deltaChart
    .width(300)
    .height(250)
    .dimension(bfeDeltaDim)
    .group(pointsByBFEDelta)
    .ordering(function(d) {
        if(d.key == "5 ft") return 0;
        else if(d.key == "4 ft") return 1;
        else if(d.key == "3 ft") return 2;
        else if(d.key == "2 ft") return 3;
        else if(d.key == "1 ft") return 4;
        else if(d.key == "0 ft") return 5;
        else if(d.key == "-1 ft") return 6;
        else if(d.key == "-2 ft") return 7;
        else if(d.key == "-3 ft") return 8;
        else if(d.key == "-4 ft") return 9;
        else if(d.key == "-5 ft") return 10;
        else return 11;
    })
    .xAxis().ticks(4);

Upvotes: 1

Craicerjack
Craicerjack

Reputation: 6332

If the strings are like they are above you could work with them in the function.
Split:

The split() method splits a String object into an array of strings by separating the string into substrings.

split the string by the space in the string and then return the first item in the array
Then parse this item, which will be 5 to -5 into an int

.ordering(function(d){  
     return parseInt(d.split(" ")[0]);  
 })

Upvotes: 1

Terry
Terry

Reputation: 66228

Are you sure d3.js has an .ordering() method? Perhaps you are looking for the good old .sort(). The issue is that you have to replace the unit "ft" when iterating through the array, and we can use the regex pattern \s+ft$ to remove that. The pattern matches the term <any_amount_of_space>ft at the end of the string. After replacement, simply convert it to a float. I avoid using parseInt() because you might have non-integer values.

var arr = ["5 ft", "4 ft", "3 ft", "2 ft", "1 ft", "0 ft", "-1 ft", "-2 ft", "-3 ft", "-4 ft", "-5 ft"];

var arr_sorted = arr.sort(function(a, b) {
  // Convert to float
  var x = parseFloat(a.replace(/\s+ft$/, "")),
      y = parseFloat(b.replace(/\s+ft$/, ""));

  // Return, sort by descending order
  return ((x < y) ? 1 : ((x > y) ? -1 : 0));

  // If ascending order is needed, use:
  // return ((x > y) ? 1 : ((x < y) ? -1 : 0));
});
console.log(arr_sorted);

Upvotes: 1

Related Questions