While custom axis labels is a little tricky, here’s a sneaky way to replace the “bad” axis tick labels d3 uses with the “good” ones you want to use (whatever that might mean).

My data in this example is normal years - 1950, 1951, 1952…all the way up to the 2000’s. But look at that axis!

Open example in new window

...
    // STEP ONE: Use .tickValues to explicitly set the labels
    var xAxis = d3.axisBottom(xPositionScale)
      .tickValues([1955, 1965, 1975, 1985, 1995, 2005]);

    // STEP TWO: Tell d3 to draw its normal year-ish labels...
    svg.append("g")
      .attr("class", "axis x-axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

    // STEP THREE: Overwrite d3's labels with your own
    svg.selectAll(".x-axis text").text(function(d) { 
      switch(d) {
        case 1955: return "Fifties";
        case 1965: return "Sixties";
        case 1975: return "Seventies";
        case 1985: return "Eighties";
        case 1995: return "Nineties";
        case 2005: return "Aughts";
      }
      return "Unknown"
    })
...

Open example in new window

You’re basically just taking what d3 wrote and saying “no no that’s all wrong, let me do it again for you.” The initial drawing by d3 and then your redrawing happens so fast you don’t see “1955”, only “Fities.”

Be sure to click Open example in new window to check all of the code out.

svg.selectAll(".x-axis text") just means “give me all of the text elements inside of .x-axis. It’s a shorter way of writing svg.select(".x-axis").selectAll("text")

Note that d in the last part isn’t your datapoint, it’s the actual value used to write the text. Also note that I used 1965 and not "1965" - even though it’s a text element, d3 is working with numbers, not text.