AME
AME

Reputation: 2609

How can I transform my objects with data to input for dygraphs?

I have a list of timeserieses. Each timeseries conists of objects that contain a timestamp and a value. The timestamps of the different timeserieses may or may not overlap. I want to plot these timeserieses in one DyGraph.

An example:

    data["first series"]  = [{timestamp: 1, value: 10.3},
                             {timestamp: 3, value: 12.5}]
    data["second series"] = [{timestamp: 2, value: 11.5},
                             {timestamp: 3, value: 13.0},
                             {timestamp: 4, value: 14.3}]

What's the most efficent way to transform my input data to a form suitable for DyGraph?

Upvotes: 0

Views: 640

Answers (1)

kaliatech
kaliatech

Reputation: 17867

I had to do the exact same for a dygraphs project recently. At a high level, you will need to create a combined dataset so that there is one row per unique x value across all of your series. For the columns/series that do not have a value at given x, you can insert a null.

I'll paste the general code I used here. This is a quick copy-paste and has been heavily modified, variables renamed, etc. It likely has a few minor errors. I was also using min/max with dygraph's customBars, which is why this code as pasted is using arrays for columns even where it probably isn't necessary.

function combineSeries(seriesArr) {

  var dyDataRows = [];

  for (var seriesIdx = 0; seriesIdx < seriesArr.length; seriesIdx++) {

    var seriesData = seriesArr[seriesIdx];

    var newDyDataRows = [];

    var nextDataRowInsertIdx = 0;
    for (var dpIdx = 0; dpIdx < seriesData.length; dpIdx++) {
      var dp = seriesData[dpIdx];

      if (nextDataRowInsertIdx < dyDataRows.length) {
        var nextDataRowCols = dyDataRows[nextDataRowInsertIdx];
        var nextDataRowX = nextDataRowCols[0].getTime();
      }

      if (nextDataRowInsertIdx >= dyDataRows.length || dp.x < nextDataRowX) {
        var newDataRowCols = [new Date(dp.x)];
        for (var colIdx = 0; colIdx < seriesIdx; colIdx++) {
          newDataRowCols.push([null]);
        }
        newDataRowCols.push([dp.y]);
        newDyDataRows.push(newDataRowCols);
      }
      else if (dp.x > nextDataRowX) {
        var newDataRowCols = nextDataRowCols.slice(0);
        newDataRowCols.push([null]);
        newDyDataRows.push(newDataRowCols);
        nextDataRowInsertIdx++;
        dpIdx--;
      }
      else {//(dp.x == nextDataRowX) {
        var newDataRowCols = nextDataRowCols.slice(0);
        newDataRowCols.push([dp.y]);
        newDyDataRows.push(newDataRowCols);
        nextDataRowInsertIdx++;
      }

    }

    //insert any remaining existing rows
    for (var i = nextDataRowInsertIdx; i < dyDataRows.length; i++) {
      var nextDataRowCols = dyDataRows[i];
      var nextDataRowDateTm = nextDataRowCols[0];

      var newDataRowCols = nextDataRowCols.slice(0);
      newDataRowCols.push([null]);
      newDyDataRows.push(newDataRowCols);
    }

    dyDataRows = newDyDataRows;
  }

  return dyDataRows;
};

This is brute force approach, and there are likely more efficient JavaScript coding techniques. It worked for me though.

Upvotes: 2

Related Questions