Hi,
here is what I’m trying to do: subtract an average (or median) value from a time series.
Application: I have a bunch of temperature sensors, where I’m not interested in the absolute value of each individual sensor, but rather the deviation from the average value (per sensor).
I have those two queries, which both work indivually.
t2 = from(bucket: "VIS")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] =~ /${temperatures:regex}/)
|> mean()
|> group(columns: ["_measurement"])
|> yield()
t1 = from(bucket: "VIS")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] =~ /${temperatures:regex}/)
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
How can I combine the aggregated values and the timeseries ? (I essentially want t1-t2)
I tried |> map but I failed finding the correct syntax/function.
Any advice appreciated !
Hi @brainiac,
Welcome to the community! I trust you are doing well. You’re not far off, here is an example query with my data:
var1 = from(bucket: "Jetson")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "exec_jetson_stats")
|> filter(fn: (r) => r["_field"] == "jetson_CPU1" )
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
var2 = from(bucket: "Jetson")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "exec_jetson_stats")
|> filter(fn: (r) => r["_field"] == "jetson_CPU2")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
union(tables: [var1, var2])
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> map(fn: (r) => ({ r with deviation: r.jetson_CPU1 - r.jetson_CPU2}))
|> yield(name: "mean")
The part that’s important:
- I use a union to merge my two tables into one table.
- I then pivot based on the _field key to turn my CPU1 and CPU2 into two separate columns.
- As you said I then use the map function to generate a new column based on my desired calculation.
Thanks @Jay_Clifford but I think that’s not quite what I wanted.My problem is, that var1 has no “_time” since it’s an aggregate function.
I have reformulated my problem to a minimal example:
import "sampledata"
t1 = sampledata.float()
|> mean()
|> yield(name: "_average")
t2 = sampledata.float()
|> yield(name: "_individual")
t2-t1
So what I want is the table that looks like _individual but has subtracted the average value (from t2) based on the tag.
Is this possible ?
Hi @brainiac,
Sorry for the miss read. In that case you are looking for a join on the tag:
import "sampledata"
t1 = sampledata.float()
|> mean()
t2 = sampledata.float()
join(
tables: {t1: t1, t2: t2},
on: ["tag"],
)
|> map(fn: (r) => ({ r with _value: r._value_t2 - r._value_t1 }))
|> yield(name: "custom-name")
Thanks @Jay_Clifford, that worked (with a bit of tweaking)!
Just for reference, I’m posting the solution for my initial Query.
There might be a more elegant way of doing this, but it works flawlessly
t1 = from(bucket: "VIS")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] =~ /${temperatures:regex}/)
|> mean()
|> group(columns: ["_measurement"])
t2 = from(bucket: "VIS")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] =~ /${temperatures:regex}/)
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
join(
tables: {t1: t1, t2: t2},
on: ["_measurement"],
)
|> map(fn: (r) => ({ r with _value: (r._value_t1 - r._value_t2) }))
|> rename(columns: {_start_t1: "_start", _stop_t1: "_stop", _field_t1: "_field"})
|> drop(columns:["_value_t1", "_value_t2", "_start_t2", "_stop_t2", "_field_t2"])
|> group(columns: ["_measurement", "_field", "_start", "_stop"])
|> yield()