score:1

Accepted answer

since domain to d3.scale is exclusive, I have to include 2017 in order to have axis drawn to the end of the chart.

Well, that's not correct. If you set the domain to be:

[1982, 2016]

The first value in the domain will be 1982 and the last one will be 2016, it's simple as that.

The problem you're facing here is the axis generator. In D3, the ticks are dynamically generated, and sometimes it's difficult to get the ticks you want.

For instance, check this snippet, in which the domain is [1992, 2016]:

var svg = d3.select("svg");

var xScale = d3.scale.linear().domain([1992,2016]).range([10,490])
var xAxis = d3.svg.axis().orient('bottom').scale(xScale);
var gX = svg.append("g").attr("transform","translate(0,50)").call(xAxis);
path, line {
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

text{
  font-size:8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="500" height="80"></svg>

As you can see, 2016 is there, no problem. But now the same code, starting at 1982 instead of 1992:

var svg = d3.select("svg");

var xScale = d3.scale.linear().domain([1982,2016]).range([10,490])
var xAxis = d3.svg.axis().orient('bottom').scale(xScale);
var gX = svg.append("g").attr("transform","translate(0,50)").call(xAxis);
path, line {
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

text{
  font-size:8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="500" height="80"></svg>

2016 is not there anymore (even 1982 is absent).

Solution: There are some different ways to force the axis to show some ticks, like using nice() in the scale. But even nice() is not guaranteed to work every time.

One way to guarantee that the first and last value in the domain will show up in the axis is using tickValues and passing an array of values concatenated with the scale domain, like this:

tickValues(xScale.ticks(20).concat(xScale.domain()))

The problem with this approach is that, depending on the number of ticks in ticks(), the end ticks are not evenly spaced.

Check the snippet:

var svg = d3.select("svg");

var xScale = d3.scale.linear().domain([1982,2016]).range([10,490])
var xAxis = d3.svg.axis().orient('bottom').scale(xScale).tickValues(xScale.ticks(20).concat(xScale.domain()));
var gX = svg.append("g").attr("transform","translate(0,50)").call(xAxis);
path, line {
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

text{
  font-size:8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="500" height="80"></svg>

Regarding the comma, the other answer has got you covered.

score:2

I believe this similar question & answer may help: D3 remove comma delimiters for thousands

For your code:

var xAxis = d3.svg.axis().orient('bottom').scale(xScale).ticks(34).tickFormat(d3.format("d"));

Related Query

More Query from same tag