Line chart: align x axis (timestamps) for multiple data sets

๐Ÿ‘:0

I would use a library like lodash (to make utility things quicker) to pre process the data into a flat list of all timestamps and then for each dataset a matching list of values recording null if that data set does not have a timestamp from the merged flat list of all timestamps.

I have also added an option to my fork of chart js which would be useful here which would be to then populate sparse data to the lines still connect and you are not left with floating points that can be hard to see.

var datasets = {
  "Default": {
    "Values": [
      999,
      799,
      999
    ],
    "Timestamps": [
      "2015-03-01T03:31:16+00:00",
      "2015-03-01T07:21:43+00:00",
      "2015-03-01T14:02:22+00:00"
    ]
  },
  "Current": {
    "Values": [
      399,
      849
    ],
    "Timestamps": [
      "2015-03-01T01:15:22+00:00",
      "2015-03-01T21:30:43+00:00"
    ]
  },
  "CurrentPremium": {
    "Values": [
      500,
      345,
      200,
      500
    ],
    "Timestamps": [
      "2015-02-01T14:24:00+00:00",
      "2015-03-01T00:13:28+00:00",
      "2015-03-01T09:56:43+00:00",
      "2015-03-01T12:00:04+00:00"
    ]
  }
};

//merge and sort all timestamps in to one array (used lodash here just to make things easy
var timestamps = _.chain(datasets).pluck("Timestamps").reduce(function(previous, current, index) {
  return previous.concat(current)
}).unique().sortBy(function(timestamp) {
  return new Date(timestamp)
}).value();


//set up base chart data with colours
var chartDatasets = [{

  fillColor: "rgba(220,120,120,0.2)",
  strokeColor: "rgba(220,120,120,1)",
  pointColor: "rgba(120,120,120,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(220,220,220,1)",

}, {

  fillColor: "rgba(20,120,120,0.2)",
  strokeColor: "rgba(20,120,120,1)",
  pointColor: "rgba(20,120,120,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(220,220,220,1)",

}, {

  fillColor: "rgba(120,120,120,0.2)",
  strokeColor: "rgba(120,120,120,1)",
  pointColor: "rgba(120,120,120,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(220,220,220,1)",

}]



//go through each dataset from server,
//for each dataset go through it's time stamps,
//go through the merged timestamps and if the timestamp is prresent in the dataset record the value other wise record null so we
//end up with a flat list of data that matches the flat time stamps
var datasetsIndex = 0;
_.forEach(datasets, function(dataset, key) {
  var data = [];
  _.forEach(timestamps, function(timestamp) {
    var dataToPush = null;
    _.forEach(dataset.Timestamps, function(datasetTimestamp, datasetTimestampIndex) {
      if (datasetTimestamp === timestamp) {
        dataToPush = dataset.Values[datasetTimestampIndex];
      }
    });
    data.push(dataToPush);

  });

  chartDatasets[datasetsIndex].label = key;
  chartDatasets[datasetsIndex].data = data;
  datasetsIndex++;
});

var chartData = {
  labels: timestamps,
  datasets: chartDatasets
};


var chart = new Chart(document.getElementById("chart").getContext("2d")).Line(chartData, {
  populateSparseData: true
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.3.1/lodash.js"></script>
<script src="http://quincewebdesign.com/cdn/Chart.js"></script>
<canvas id="chart" width="400" height="400"></canvas>

Leave a comment