如何使用 InfluxDB 跟踪天气预报截至预测日期的变化情况

问题描述 投票:0回答:2

我正在尝试总体熟悉 InfluxDB 和时间序列数据库,并想知道这是否是一个合适的用例。

考虑截至预测日期的天气预报。假设每天您都会预测接下来 5 天的最高温度,因此对于每个实际日期,您都会有 5 个预测的最高温度值,后跟实际值。

因此时间戳就是进行预测的日期,但是您使用什么来表示预测的时间呢?我认为在这种情况下,预测可能是针对给定日期的,但也可能是针对日期的子集的。这会是一个标签吗?

influxdb
2个回答
0
投票

我也有同样的问题。我用时间戳和标签解决了它:

  1. timestamp:将预测值放在预测时间的时间戳上。
  2. 为每个值添加一个tag
    'age_h'
    (在我的例子中,预测的年龄以小时为单位)我知道,标签只能是字符串,但我仍然可以添加一个数字作为字符串。这里的年龄实际上是未来的年龄。因此,如果今天您添加 2 天后的预测,age_h 标签将变为
    48
    。如果您将来再次查看该点,您就会知道该值是在该值的实际时间戳之前 48 小时预测的。 您将获得相同时间戳的一系列值,但根据其年龄,它们将具有不同的预测 Age_h 和不同的准确概率。 如果您搜索最近的预测,请查找age_h 数字最小的值。 (这可以在不断变化的情况下完成吗?我不知道如何。)
  3. 不要这样做,请参阅下面的编辑向每个值添加一个标签
    'forecast_series'
    给出时间,进行预测。同样,只允许使用字符串,但这并不能阻止我添加它。
    <year><month><day><hour>
    (我首先有分隔符,但后来意识到,如果我可以将其解析为数字,比较会更容易)。此标签确保您可以在需要该维度时找到预测/预测系列。

我还没有得到很多数据,所以我需要看看它是否按预期工作。

你是怎么解决的?

编辑: 显然第三个标签是个坏主意。突然间,我的免费在线存储桶不想再获取任何数据。出现以下错误:

Oh no! You hit the series cardinality limit and your data stopped writing.

标签的取值范围不应稳定增加。应限制使用的标签及其值的范围,以保持数据库快速且精简。

所以我发现第三个标签其实可以从timestamp和age_h标签中扣除。

现在这是一个非常简洁的查询,用于显示带有标签age_h == '0'的所有值的图表(过去的值)和对未来值的最新预测。

如果您想了解更多详情,请留言。 如果可以改进,请赐教:-)

import "strings"
import "system"
import "date"
import "timezone"

hours = (h) => duration(v:(h)*1000000000*3600)

to_int_hours = (t) => {
  datestr = string(v:t)
  year = strings.substring(v: datestr, start: 0, end: 4)
  mon = strings.substring(v: datestr, start: 5, end: 7)
  day = strings.substring(v: datestr, start: 8, end: 10)
  hour = strings.substring(v: datestr, start: 11, end: 13)
  return int(v: year+mon+day+hour)
}

forecast_datetime = (t, z, a) => { //time, zone_h, age_h_string
  a_h = int(v: a)
  forecast_date = date.add(d: hours(h:z-a_h), to: t)
  return to_int_hours(t:forecast_date)
}

local_zone = 2 //my zone: UTC+2
local_now = date.add(d: hours(h:local_zone-1), to: system.time())
query_datetime = to_int_hours(t:local_now)

rangeStop = date.add(d: 48h, to: v.timeRangeStop)

from(bucket: "Energy")
  |> range(start: v.timeRangeStart, stop: rangeStop)
  |> filter(fn: (r) => r._measurement == "meteo-forecast")
  |> filter(fn: (r) => r._field == "TTT_C"  or r._field == "FF_KMH")
  |> filter(fn: (r) => r.age_h == "0")
  |> drop(columns: ["age_h"])
  |> sort(columns: ["_time"])
  |> yield(name: "temperature_wind_past")
from(bucket: "Energy")
  |> range(start: v.timeRangeStart, stop: rangeStop)
  |> filter(fn: (r) => r._measurement == "meteo-forecast")
  |> filter(fn: (r) => r._field == "TTT_C" or r._field == "FF_KMH")
  |> filter(fn: (r) => forecast_datetime(t:r._time, z:local_zone, a:r.age_h) >= query_datetime)
  |> drop(columns: ["age_h"])
  |> sort(columns: ["_time"])
  |> yield(name: "temperature_wind_forecast")
from(bucket: "Energy")

0
投票

我遇到了同样的问题,并以更简单的方式解决了,在 influxdb2 中使用组/过滤器。最好的方法仍然是使用“标签”来存储预测距离未来多远,并存储

time == predTime

import "system" // Optional if we want to filter future values

from(bucket: "data")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "pred")
  |> filter(fn: (r) => r["_field"] == "water" or r["_field"] == "temp")
// Optional if we want to filter future values
  |> filter(fn: (r) => r._time >= system.time())
// Optional, if our tags are not alphabetically ordered
//  |> map(fn: (r) => ({r with hours: float(v: r.hours)}))
// Groups by key time & field, "hour" becomes a distinct feature of the table
  |> group(columns:["_time", "_field"]) 
// Get the lowest "hours" in the table
  |> bottom(n: 1, columns: ["hours"])
// ungroup is necessary to avoid having multiple tables
  |> group() 
// pivot the table to separate the fields into columns
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")

只要“小时”或分钟、秒或任何其他用于排序的标签格式有效。例如“001”、“002”。

不要以

1
10
200.8
格式存储标签,否则字符串中的明智排序将不起作用。在调用
map()
之前,它们需要先
bottom()
转换为整数/双精度数:

  |> map(fn: (r) => ({r with hours: float(v: r.hours)}))
© www.soinside.com 2019 - 2024. All rights reserved.