Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure flot to draw missing time series on y-axis at point zero?

I'm using flot (flot on github) to draw a graph with the following time series data:

[
    [1357171200000, 1],
    [1357344000000, 1],
    [1357430400000, 2],
    [1357516800000, 2],
    [1357689600000, 3],
    [1357776000000, 1]
]

As you can see there are some points in the graph wich show the sales for the given day. My json response doesn't contain sales count / data for days where no sale has happened. For example the 04th of January. How can i configure flot to draw the missing days on y-axis at point zero (because there are no sales)? As you can see in the image flot does connect the points so there are no zero points in the graph.

Graph

like image 944
whitenexx Avatar asked Jan 25 '13 13:01

whitenexx


2 Answers

Here's a solution that creates a new Array adding in missing days and setting their values to zero:

/* create and return new array padding missing days*/
function newDataArray(data) {
  var startDay = data[0][0],
    newData = [data[0]];

  for (i = 1; i < data.length; i++) {
    var diff = dateDiff(data[i - 1][0], data[i][0]);
    var startDate = new Date(data[i - 1][0]);
    if (diff > 1) {
      for (j = 0; j < diff - 1; j++) {
        var fillDate = new Date(startDate).setDate(startDate.getDate() + (j + 1));
          newData.push([fillDate, 0]);
      }
    }
    newData.push(data[i]);
  }
  return newData;
}


/* helper function to find date differences*/
function dateDiff(d1, d2) {
  return Math.floor((d2 - d1) / (1000 * 60 * 60 * 24));
}

To use:

var data = [
  [1357171200000, 1],
  [1357344000000, 1],
  [1357430400000, 2],
  [1357516800000, 2],
  [1357689600000, 3],
  [1357776000000, 1]
];

var newData=newDataArray(data);
/* pass newData to flot*/

DEMO: http://jsfiddle.net/LK2gD/3/

like image 178
charlietfl Avatar answered Nov 18 '22 22:11

charlietfl


So, you have daily count. You can then iterate over each entry and find the number of day between the current entry and the next one, then you will just need to fill you array with 0.

It is much better to use an zero filled array and then add only the count for the date you have in your current array, then you will not need to do any check on the date.

You daily interval

var millisInDay = 1000*60*60*24;

This will give you the number of daily interval

  var intervals = parseInt(((lastDateInMillis - startDateInMillis)/
                                  millisInDay) + 1);

Then when you iterate over your array of date

[[1357171200000, 1], [1357344000000, 1], [1357430400000, 2], 
[1357516800000, 2], [1357689600000, 3], [1357776000000, 1]]

Check in which interval is the date, and update the count in the 'interval' array (counts)

var interval = ((currentDateMillis - startDateInMillis) / millisInDay);
counts[interval] += currentCount; 

And then you can play with index to map the count with a particular day:

function getEpochStartInterval(index){
  return startDateInMillis + (index * millisInDay);
}

function getEpochEndInterval(index){
  return startDateInMillis + ((index + 1) * millisInDay);
}
like image 2
JohnJohnGa Avatar answered Nov 19 '22 00:11

JohnJohnGa