首页 > 解决方案 > 根据时间获取滚动平均值

问题描述

我有一个包含两个变量的大型数据集,一个时间和一个值。我需要为每条线创建一个滚动平均值的新数据集,计算过去 60 分钟(包括当前线)的所有值的平均值。

我尝试了一些使用 tq_mutate 和其他方法的东西,但无法真正做到这一点。

这是一个示例数据:

data= structure(list(time= structure(c(1407626653, 1407626709, 
1407629849, 1407629927, 1407630463, 1407631433), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), value= c(4, 1, 4, 3, 2, 3
)), .Names = c("time", "value"), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

这是预期的结果:

data = structure(list(time = structure(c(1407626653, 1407626709, 1407629849, 
1407629927, 1407630463, 1407631433), class = c("POSIXct", "POSIXt"
), tzone = "UTC"), value = c(4, 1, 4, 3, 2, 3), expected = c(4, 
2.5, 3, 3, 3, 3)), .Names = c("time", "value", "expected"), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

标签: r

解决方案


您将看到的大多数方法都涉及以某种方式用大量 0/NA 填充数据并使用rollapply/ rollmean(它基于 # 个观察窗口而不是时间间隔,尽管rollapply您可以为每个观察提供自定义窗口大小(根据观察))。

data.table包允许您通过在时间列上将表连接到自身来有效地执行此操作,这样我们只考虑前一小时。

library(data.table)
library(lubridate) # <-- only need for `- hours(1)` convenience, not strictly necessary
                   # Could instead do `- 60*60` and not load this package

setDT(data)[                                            #<Turn `data` in to a `data.table`
    J(end=unique(time), start=unique(time) - hours(1)), #<Define the start time=1 hour ago
                                                        #   and end time=current time.
    on=.(time <= end, time >= start),                   #<Join to itself restricting the
                                                        #   time to be within these windows
    list(value = mean(value)),                          #<Calc avg value
    by=.EACHI                                           #<For each join group (time window)
][,
    list(time, value)                                   #<Select the desired columns out
]                                                       # (o'wise you will get two
                                                        # identical "time" columns)

# output
                  time value
                <POSc> <num>
1: 2014-08-09 23:24:13   4.0
2: 2014-08-09 23:25:09   2.5
3: 2014-08-10 00:17:29   3.0
4: 2014-08-10 00:18:47   3.0
5: 2014-08-10 00:27:43   3.0
6: 2014-08-10 00:43:53   3.0

还有其他选项,比如简单地编写一个“为每一行,在我当前时间之后 1 小时内找到所有行,并计算平均值”——就像这个解决方案一样,它们只是有点“手动”。


推荐阅读