Question

I have an issue where I try to display average values over a single day; Hours, minutes (%H:%M), but the chart does not properly interpret the data and switches times around, 23:30 comes after 00:00, creating a messy display.

I think the issue is related to how time formatting, but am not sure how. Can anyone identify what is wrong? Any tips are appreciated!

Code

<script>
d3.csv("17_predicted_hourly_holiday.csv", function(error, data) {

  data.sort(function(a, b) {
    return a.length - b.length;
  });

  var exampleData = Object.keys(data[0]).filter(function(k) {
    return k != 'length'
  })
    .map(function(k) {
      return {
        'key': k,
        'values': data.map(function(d) {
          return [
            d3.time.format('%Y-%m-%d' + '%H:%M').parse("2000-01-01" + d.length),
            //d3.time.format('%Y-%b-%d' + '%H:%M:%S').parse("2000-01-01" + d.length + ':00')
            +d[k]
          ]
        })
      }
    });

  //alert(JSON.stringify(exampleData));
  console.log(exampleData);
  //console.log(data);

  var colors = d3.scale.category20();
  keyColor = function(d, i) {
    return colors(d.key)
  };

  var chart;

  nv.addGraph(function() {
    chart = nv.models.stackedAreaChart()
      .x(function(d) {
        return d[0]
      })
      .y(function(d) {
        return d[1]
      })
      .color(keyColor)
      .clipEdge(true);

    chart.xAxis
      .tickFormat(function(d) {
        return d3.time.format('%H:%M')(new Date(d));
      });
    chart.yAxis
      .tickFormat(d3.format(',.2f'));

    d3.select('#chart')
      .datum(exampleData)
      .transition().duration(500).call(chart);
    nv.utils.windowResize(chart.update);
    chart.dispatch.on('stateChange', function(e) {
      nv.log('New State:', JSON.stringify(e));
    });
    return chart;
  });
  // end read csv
});

Plunker

http://plnkr.co/edit/GYI8oq?p=info

Image of issue: http://i.imgur.com/li1Vee2.png

Was it helpful?

Solution

The problem is that in your sorting function you're assuming that length is a number, which it is not. In your case, you don't even need to sort though as the data comes in sorted. Working example here.

Alternatively, you can use a sort function that works with the times:

data.sort(function(a, b) {
    return d3.time.format('%Y-%m-%d' + '%H:%M').parse("2000-01-01" + a.length) - d3.time.format('%Y-%m-%d' + '%H:%M').parse("2000-01-01" + b.length);
  });

Complete demo here.

On a general note, don't use length as an attribute name -- it clashes with the .length that gives you the length of an array in Javascript and will cause problems sooner or later.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top