S.H
S.H

Reputation: 703

Barchart "dates" are displaying strange / bars are pressed

I want to create a barchart displaying C02 emission.

The Problem (see picture below):

Why are the bars "pushed" to the right? Why are the years in the x-axis displayed without the first integer?

I am using Version 3 of d3.

Given some JSON data like this:

     [
      {
        "Cement": 0.0,
        "Gas Flaring": 0.0,
        "Gas Fuel": 0.0,
        "Liquid Fuel": 0.0,
        "Per Capita": null,
        "Solid Fuel": 3.0,
        "Total": 3.0,
        "Year": 1751
      }, 
and so on…
]

To prepare for scaling I did:

  var minDate = dataset[0].Year;
  var maxDate = dataset[dataset.length - 1].Year;

 var maxValue = d3.max(dataset, function(d) {
    return d["Per Capita"];
  });

I append the svg

var svg = d3
    .select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);

I sacled the xAxis and the yAxis:

  var xAxisScale = d3.time
    .scale()
    .domain([minDate, maxDate])
    .range([0, w]);

  var yAxisScale = d3.scale
    .linear()
    .domain([0, maxValue])
    .range([h, 0]);

The I finally builded these axisses…

 var xAxis = d3.svg
    .axis()
    .scale(xAxisScale)
    .orient("bottom");

  var yAxis = d3.svg
    .axis()
    .scale(yAxisScale)
    .orient("left");

  svg
    .append("g")
    .attr("class", "axis")
    .attr("transform", "translate(92," + (h - padding) + ")")
    .call(xAxis);

  svg
    .append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + padding + ",-90)")
    .call(yAxis);

I also than addeded the rects…

  svg
    .selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .style("fill", "teal")
    .attr({
      x: function(d, i) {
        return i * (w / dataset.length);
      },
      y: function(d) {
        return yAxisScale(d["Per Capita"]);
      },
      width: w / dataset.length,
      height: function(d) {
        return h - yAxisScale(d["Per Capita"]);
      }
    });

The result is not the intended one. The bars are "pressed" to the right. The x-sclales Years have these floating point instead of the Millenia

Could you please elaborate what went wrong?

Why are the bars "pushed" to the right? Why are the years in the x-axis displayed without the first integer?

I am using Version 3 of d3.

Thank you very much!

Upvotes: 1

Views: 41

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

The main problem here is that this...

"Year": 1751

... is not a date object. That's just a number. If you look at your axis you'll realise that.

So, you have to parse it. For instance:

const format = d3.time.format("%Y");
dataset.forEach(function(d){
    d.Year = format.parse(d.Year);
});

Also, when you do this...

var minDate = dataset[0].Year;
var maxDate = dataset[dataset.length - 1].Year;

... you're blindly trusting that the array is sorted. Don't do that. Instead, do:

var minDate = d3.max(dataset, function(d){
    return d.Year
});
var maxDate = d3.min(dataset, function(d){
    return d.Year
});

Or, if you want to use destructuring:

var [minDate, maxDate] = d3.extent(dataset, d => d.Year);

Finally, now that you have a proper scale, don't use the indices for the x position. Use the scale:

x: function(d) {
    return xAxisScale(d.Year);
},

This covers the problem regarding the x position. For fixing the y position, just set a proper margin.

Upvotes: 1

Related Questions