Combining separate temporal measurement series

Viewed 34

I have a data set that combines two temporal measurement series with one row per measurement

time:  1, measurement: a, value: 5
time:  2, measurement: b, value: false
time: 10, measurement: a, value: 2
time: 13, measurement: b, value: true
time: 20, measurement: a, value: 4
time: 24, measurement: b, value: true
time: 30, measurement: a, value: 6
time: 32, measurement: b, value: false

in a visualization using Vega lite, I'd like to combine the measurement series and encode measurement a and b in a single visualization without simply layering their representation on a temporal axis but representing their value in a single encoding spec.

either measurement a values need to be interpolated and added as a new value to rows of measurement b

eg:

time: 2, measurement: b, value: false, interpolatedMeasurementA: 4.6667

or the other way around, which leaves the question of how to interpolate a boolean. maybe closest value by time, or simpler: last value

eg:

time: 30, measurement: a, value: 6, lastValueMeasurementB: true

I suppose this could be done either query side in which case this question would be regarding indexDB Flux query language

or this could be done on the visualization side in which case this would be regarding vega-lite

1 Answers

There's not any true linear interpolation schemes built-in to Vega-Lite (though the loess transform comes close), but you can achieve roughly what you wish with a window transform.

Here is an example (view in editor):

{
  "data": {
    "values": [
      {"time": 1, "measurement": "a", "value": 5},
      {"time": 2, "measurement": "b", "value": false},
      {"time": 10, "measurement": "a", "value": 2},
      {"time": 13, "measurement": "b", "value": true},
      {"time": 20, "measurement": "a", "value": 4},
      {"time": 24, "measurement": "b", "value": true},
      {"time": 30, "measurement": "a", "value": 6},
      {"time": 32, "measurement": "b", "value": false}
    ]
  },
  "transform": [
    {
      "calculate": "datum.measurement == 'a' ? datum.value : null",
      "as": "measurement_a"
    },
    {
      "window": [
        {"op": "mean", "field": "measurement_a", "as": "interpolated"}
      ],
      "sort": [{"field": "time"}],
      "frame": [1, 1]
    },
    {"filter": "datum.measurement == 'b'"}
  ],
  "mark": "line",
  "encoding": {
    "x": {"field": "time"},
    "y": {"field": "interpolated"},
    "color": {"field": "value"}
  }
}

enter image description here

This first uses a calculate transform to isolate the values to be interpolated, then a window transform that computes the mean over adjacent values (frame: [1, 1]), then a filter transform to isolate interpolated rows.

If you wanted to go the other route, you could do a similar sequence of transforms targeting the boolean value instead.

Related