Reputation: 99
I'm currently plotting a list of numbers (y-axis) against a list of titles (x-axis). Each number can correspond to multiple websites. Right now I've been using the ascending function provided by d3 to sort them. I've currently got a drop-down menu in which I can pick either number or title and each option individually sorts by the respective choice. However, I was wondering if there was a way so that I could sort alphabetically by title, and then keeping it alphabetical, also sort by number. As of now I can only do one or the other.
Example: My data is stored in a CSV like this:
"id","name"
1,"youtube"
1,"google"
2,"google"
3,"nike"
4,"google"
Then I use
d3.csv("csvTestFile.csv", function (dataset)
to read in the file and I convert the id number to ints.
To sort I do the following:
data.sort(function(a, b) { return d3.ascending(a.id, b.id)});
To sort by ID. To sort by name I do this:
data.sort(function(a, b) { return d3.ascending(a.name, b.name)});
Both of these work properly, however I would like to first sort by ID, then also sort by Name. So the axis would display (starting from the origin) 1, 2, 3, 4 up the y-axis, and google, nike, youtube down the x-axis. Right now if I try to sort it will either be 1, 2, 3, 4 up to the y-axis and youtube, google, nike down the x-axis OR google, youtube, nike down the x-axis with 1, 2, 4, 3 up the y-axis.
What I want is 1, 2, 3, 4 up the y-axis (sorted numerically) and google, nike, youtube down the x-axis (sorted alphabetically) at the same time. Given this is a scatterplot it should be something simply like rearranging the ticks on the axis but I'm not quite sure how to go about doing it.
Upvotes: 0
Views: 2840
Reputation: 109232
The order in which input values are mapped to output values for a categorical scale depends on the order in which they are given to .domain()
. All you need to do to achieve what you want is to sort the values accordingly when you create the scale, i.e. something like
var scale = d3.scale.ordinal()
.domain(data.sort(function(a, b) { return d3.ascending(a.name, b.name); }))
.range([...]);
Upvotes: 3