20

I want to crate a bar chart using strings as the labels for the ticks on the x-axis (e.g., Year 1, Year 2, etc instead of 0,1,2, etc).

I started by using the numeric values for the x-axis (e.g., 0,1,2,3, etc) as follows:

1) I generate my ranges:

     x = d3.scale.ordinal()
        .domain(d3.range(svg.chartData[0].length)) //number of columns is a spreadsheet-like system
        .rangeRoundBands([0,width], .1); 


     y = d3.scale.linear()
        .domain(Math.min(d3.min(svg.chartData.extent),0), Math.max(d3.min(svg.chartData.extent),0)]) 
        .range([height, 0])
        .nice();

2) Make the axes:

     d3.svg.axis()
        .scale(x);

3) Redraw the axes:

     svg.select(".axis.x_axis")
        .call(make_x_axis().orient("bottom").tickSubdivide(1).tickSize(6, 3, 0));

This works well with default numeric axis labels.

If I try to use an array of strings for the x tickValues like this....

     d3.svg.axis()
        .scale(x).tickValues(svg.pointsNames); //svg.pointsNames = ["Year 1", "year 2", etc.]

... when I redraw the chart (with or without changes to the data/settings), the labels swap like this.

enter image description here enter image description here

Notice how Col 1 takes the place of Col 0 and vice versa.

Do you know why this happens?

royhowie
  • 11,075
  • 14
  • 50
  • 67
Gian
  • 549
  • 3
  • 7
  • 18

2 Answers2

22

Update

Just sort the svg.pointsNames before you apply them as tickValues. Make sure you sort them in exactly the same way that you sort your data. This way, a one-one mapping is always maintained between your labels and tick values.

Also if I may, check out the tickFormat` function here. This seems a better option to me.

//Tick format example
chart,xAxis.tickFormat(function(d, i){
    return "Year" + d //"Year1 Year2, etc depending on the tick value - 0,1,2,3,4"
})
Jibi Abraham
  • 4,636
  • 2
  • 31
  • 60
  • Thanks Jibi, the pointsNames are sorted as they are generated together with the numeric data: when I populate a column to chart, I push the name in the names array. I also checked in console that the pointsNames is always in the right order. The strange thing is that is starts well the first time the chart is initialized, then swaps and stayed swapped after that. So it swaps only at the first redraw. Thanks for the link: how should I use axis.tickFormat([format]) in my case? Thanks again. – Gian Aug 02 '12 at 07:06
  • 1
    I agree with @Jibi, the tickFormat function is a more clean way of solve the problem. – Pablo Navarro Aug 02 '12 at 15:31
  • @Pablo, could you please show me how to use it axis.tickFormat([format]) in my case? How can I forma [0, 1, 2, etc] that works as strings coming from another array? – Gian Aug 04 '12 at 06:18
  • I think is better to use the numeric tick values that you had before (1, 2, 3, 4, etc) and use the aforementioned `tickFormat` method to format those ticks as strings ("Year 1", "Year 2", ...). In your case: `d3.svg.axis(x).scale.tickFormat(function(d) { return "Year" + d; });` – Pablo Navarro Aug 06 '12 at 20:01
  • The tickFormat function works great. Note that it also has a second paramter, "i" in the above example, which is the index of the tick. So , about, you could return "Year" + (i+1) for "Year1, Year2", etc. – TheWestIsThe... Nov 12 '13 at 16:36
  • @Jibi, that was very useful to me too. But I ran into a problem: do you know how to ensure that all labels are displayed? In my case I have ``1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13`` but it only shows ``1, 2, 4, 6, 8, 10, 12, 13``, and (what's worse) doesn't show the vertical grid line at the missing tick labels. So after the transformations you suggest it shows Year 1, Year 2, Year 4, Year 6, etc. with several missing labels. – PatrickT Jan 16 '15 at 22:20
  • @PatrickT, I haven't worked with D3 in some time, but I think you have to ensure data for all those tick values. I guess even a zero data point will do. – Jibi Abraham Jan 19 '15 at 03:47
  • Thanks Jibi, your comments re-motivated me to try and I got it to work. It turns out I was mixing up the syntax for ``tickValues`` and ``tickFormat``, I think. I have posted my answer to my own question (sigh) here: http://stackoverflow.com/questions/27970771/rcharts-nvd3-library-force-ticks – PatrickT Jan 19 '15 at 06:34
0

Thanks for that...I used this function with an inline if-clause to handle a different x-axis series with names instead of numbers.

The factions Array consists of all relevant names sorted by the indexes of the series who then just get matched with its corresponding index in the data.

xAxis = d3.svg.axis().scale(xScale)
            .tickFormat(function(d) { 

                if(seriesX == 'seriesValue'){ 
                    return factions[d]}

                else{ 
                    return d}
            })    
         .orient("bottom");
Fabio Antunes
  • 22,251
  • 15
  • 81
  • 96
stinglsa
  • 1
  • 1
  • 1