Pivot Google DataTable on distinct values

379 Views Asked by At

I have a Google DataTable in the following format:

+----------+-------+--------+
|   time   | label | values |
+----------+-------+--------+
| 12345678 | foo   | 100    |
| 12345678 | bar   | 200    |
| 12345700 | foo   | 150    |
| 12345700 | bar   | 350    |
    ...       ...      ...

I need to create a line chart with one line per distinct "label", time on the X axis, and value on the Y axis.

To my knowledge, this requires the DataTable be in the following format:

+----------+-----+-----+
|   time   | foo | bar |
+----------+-----+-----+
| 12345678 | 100 | 200 |
| 12345700 | 150 | 350 |
    ...      ...   ...

I either need a way to pivot the DataTable into this shape, or a way to draw the LineChart I want without modifying the original DataTable.

Addendum

I can fairly easily create a DataTable in this shape with something like the following:

var newDataTable = new google.visualization.DataTable();
newDataTable.addColumn("number", "time");
var distinctLabels = oldDataTable.getDistinctValues(1);
for (var i = 0; i < distinctLabels.length; i++)
{
    newDataTable.addColumn("number", distinctLabels[i]);
}

But then the challenge is populating this table. Since the data for a single row in the new table exists on multiple rows in the first table, I can't simply iterate over every row of the old table calling .addRow() to the new table

I could utilize a hash table or some other complicated structure to parse the data and work with it, but:

  1. This seems like a problem that has an easier solution
  2. I want the best possible performance, as this LineChart will need to be redrawn each time someone interacts with a UI element on the page
1

There are 1 best solutions below

0
On BEST ANSWER

first, you could create a DataView with columns for each distinct label

then use the group() method to aggregate the label columns by timestamp

see following working snippet...

google.charts.load('current', {
  callback: drawChart,
  packages: ['corechart', 'table']
});

function drawChart() {
  var data = google.visualization.arrayToDataTable([
    ['time', 'label', 'value'],
    ['12345678', 'foo', 100],
    ['12345678', 'bar', 200],
    ['12345700', 'foo', 150],
    ['12345700', 'bar', 350],
  ]);

  var aggColumns = [];
  var viewColumns = [0];

  var distinctLabels = data.getDistinctValues(1);
  distinctLabels.forEach(function (label, index) {
    viewColumns.push({
      calc: function (dt, row) {
        if (dt.getValue(row, 1) === label) {
          return dt.getValue(row, 2);
        }
        return null;
      },
      type: 'number',
      label: label
    });
    aggColumns.push({
      column: index + 1,
      aggregation: google.visualization.data.sum,
      type: 'number'
    });
  });

  var view = new google.visualization.DataView(data);
  view.setColumns(viewColumns);

  var groupData = google.visualization.data.group(
    view,
    [0],
    aggColumns
  );

  var chart = new google.visualization.LineChart(document.getElementById('chart'));
  chart.draw(groupData);
  var table = new google.visualization.Table(document.getElementById('table'));
  table.draw(groupData);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
<div id="table"></div>