在时间序列数据框中计算特定时间窗口内的平均值

4

我的数据集在1分钟的间隔上有些嘈杂。因此,我想从第25分钟到第35分钟获取每小时的平均值,以代表该小时的30分钟。

例如,在以下时间获取平均值:00:30(从00:25到00:35的平均值),01:30(从01:25到01:35的平均值),02:30(从02:25到02:35的平均值),等等。

你能用R语言提供一个好的方法吗?

这是我的数据集:

  set.seed(1)
  DateTime <- seq(as.POSIXct("2010/1/1 00:00"), as.POSIXct("2010/1/5 00:00"), "min")
  value <- rnorm(n=length(DateTime), mean=100, sd=1)
  df <- data.frame(DateTime, value)

非常感谢。

3
我更改了你的示例的时间间隔——随机模拟一年中的每一分钟不是最简单的示例... - Chris
3个回答

3

以下是一种方法

library(dplyr)
df %>% 
  filter(between(as.numeric(format(DateTime, "%M")), 25, 35)) %>% 
  group_by(hour=format(DateTime, "%Y-%m-%d %H")) %>%
  summarise(value=mean(value))

他们希望适用于所有的10分钟间隔,而不仅仅是25-35分钟。我认为。 - Frank
不熟悉 dplyr,但如果点落入多个区间,这是否有效?我认为筛选-分组策略无法做到这一点。 - Chris
啊,我明白了。太简单了。:-> - lukeA
1
没问题,我也觉得你的解释很有道理。不过还是谢谢你恢复了它 :) - lukeA

2

如果你想对每个时间段的子集进行平均,那么首先将数据框进行子集化,然后再进行聚合是有意义的:

aggregate(
    value~cbind(time=strftime(DateTime,'%Y-%m-%d %H:30:00')),
    subset(df,{ m <- strftime(DateTime,'%M'); m>='25' & m<='35'; }),
    mean
);
##                   time     value
## 1  2010-01-01 00:30:00  99.82317
## 2  2010-01-01 01:30:00 100.58184
## 3  2010-01-01 02:30:00  99.54985
## 4  2010-01-01 03:30:00 100.47238
## 5  2010-01-01 04:30:00 100.05517
## 6  2010-01-01 05:30:00  99.96252
## 7  2010-01-01 06:30:00  99.79512
## 8  2010-01-01 07:30:00  99.06791
## 9  2010-01-01 08:30:00  99.58731
## 10 2010-01-01 09:30:00 100.27202
## 11 2010-01-01 10:30:00  99.60758
## 12 2010-01-01 11:30:00  99.92074
## 13 2010-01-01 12:30:00  99.65819
## 14 2010-01-01 13:30:00 100.04202
## 15 2010-01-01 14:30:00 100.04461
## 16 2010-01-01 15:30:00 100.11609
## 17 2010-01-01 16:30:00 100.08631
## 18 2010-01-01 17:30:00 100.41956
## 19 2010-01-01 18:30:00  99.98065
## 20 2010-01-01 19:30:00 100.07341
## 21 2010-01-01 20:30:00 100.20281
## 22 2010-01-01 21:30:00 100.86013
## 23 2010-01-01 22:30:00  99.68170
## 24 2010-01-01 23:30:00  99.68097
## 25 2010-01-02 00:30:00  99.58603
## 26 2010-01-02 01:30:00 100.10178
## 27 2010-01-02 02:30:00  99.78766
## 28 2010-01-02 03:30:00 100.02220
## 29 2010-01-02 04:30:00  99.83427
## 30 2010-01-02 05:30:00  99.74934
## 31 2010-01-02 06:30:00  99.99594
## 32 2010-01-02 07:30:00 100.08257
## 33 2010-01-02 08:30:00  99.47077
## 34 2010-01-02 09:30:00  99.81419
## 35 2010-01-02 10:30:00 100.13294
## 36 2010-01-02 11:30:00  99.78352
## 37 2010-01-02 12:30:00 100.04590
## 38 2010-01-02 13:30:00  99.91061
## 39 2010-01-02 14:30:00 100.61730
## 40 2010-01-02 15:30:00 100.18539
## 41 2010-01-02 16:30:00  99.45165
## 42 2010-01-02 17:30:00 100.09894
## 43 2010-01-02 18:30:00 100.04131
## 44 2010-01-02 19:30:00  99.58399
## 45 2010-01-02 20:30:00  99.75524
## 46 2010-01-02 21:30:00  99.94079
## 47 2010-01-02 22:30:00 100.26533
## 48 2010-01-02 23:30:00 100.35354
## 49 2010-01-03 00:30:00 100.31141
## 50 2010-01-03 01:30:00 100.10709
## 51 2010-01-03 02:30:00  99.41102
## 52 2010-01-03 03:30:00 100.07964
## 53 2010-01-03 04:30:00  99.88183
## 54 2010-01-03 05:30:00  99.91112
## 55 2010-01-03 06:30:00  99.71431
## 56 2010-01-03 07:30:00 100.48585
## 57 2010-01-03 08:30:00 100.35096
## 58 2010-01-03 09:30:00 100.00060
## 59 2010-01-03 10:30:00 100.03858
## 60 2010-01-03 11:30:00  99.95713
## 61 2010-01-03 12:30:00  99.18699
## 62 2010-01-03 13:30:00  99.49216
## 63 2010-01-03 14:30:00  99.37762
## 64 2010-01-03 15:30:00  99.68642
## 65 2010-01-03 16:30:00  99.84921
## 66 2010-01-03 17:30:00  99.84039
## 67 2010-01-03 18:30:00  99.90989
## 68 2010-01-03 19:30:00  99.95421
## 69 2010-01-03 20:30:00 100.01276
## 70 2010-01-03 21:30:00 100.14585
## 71 2010-01-03 22:30:00  99.54110
## 72 2010-01-03 23:30:00 100.02526
## 73 2010-01-04 00:30:00 100.04476
## 74 2010-01-04 01:30:00  99.61132
## 75 2010-01-04 02:30:00  99.94782
## 76 2010-01-04 03:30:00  99.44863
## 77 2010-01-04 04:30:00  99.91305
## 78 2010-01-04 05:30:00 100.25428
## 79 2010-01-04 06:30:00  99.86279
## 80 2010-01-04 07:30:00  99.63516
## 81 2010-01-04 08:30:00  99.65747
## 82 2010-01-04 09:30:00  99.57810
## 83 2010-01-04 10:30:00  99.77603
## 84 2010-01-04 11:30:00  99.85140
## 85 2010-01-04 12:30:00 100.82995
## 86 2010-01-04 13:30:00 100.26138
## 87 2010-01-04 14:30:00 100.25851
## 88 2010-01-04 15:30:00  99.92685
## 89 2010-01-04 16:30:00 100.00825
## 90 2010-01-04 17:30:00 100.24437
## 91 2010-01-04 18:30:00  99.62711
## 92 2010-01-04 19:30:00  99.93999
## 93 2010-01-04 20:30:00  99.82477
## 94 2010-01-04 21:30:00 100.15321
## 95 2010-01-04 22:30:00  99.88370
## 96 2010-01-04 23:30:00 100.06657

25-35范围只是一个例子,我认为。 - Frank
你可能是对的,如果是这样的话,那么你使用findInterval()函数就更加合适了。我们等待原帖作者的回复。 - bgoldst
2
哦,重新阅读后我认为你的解释是正确的。糟糕,让@lukeA删除了他的答案。 - Frank
@bgoldst 我认为如果点接近多个中点,这可能会导致问题。 - Chris

2

我认为现有的答案不够通用,因为它们没有考虑到时间间隔可能落在多个中点之间。

相反,我会使用 data.table 包中的 shift 方法。

library(data.table)
setDT(df)

首先根据您选择的序列设置间隔参数。这将计算表中每行周围平均十行(分钟):

df[, ave_val :=  
     Reduce('+',c(shift(value, 0:5L, type = "lag"),shift(value, 1:5L, type = "lead")))/11
   ]

然后生成您想要的中点:
mids <- seq(as.POSIXct("2010/1/1 00:00"), as.POSIXct("2010/1/5 00:00"), by = 60*60) + 30*60 # every hour starting at 0:30

然后相应地进行过滤:
setkey(df,DateTime)
df[J(mids)]

我不明白你的批评。1:25-1:35和2:25-2:35非常不连贯,对吗? - Frank
完全同意@Frank - 只是想指出现有解决方案没有考虑到另一个潜在的使用情况,即可能存在重叠的情况。 - Chris
啊,好的。是的,更好的做法可能是像你在这里做的那样,使时间间隔对称分布。 - Frank
这种方法更加灵活,可以用于其他目的。谢谢Chris!!! - Kuo-Hsien Chang
顺便说一句,我还可以使用子集来提取移动平均值后每小时的30分钟。例如,MA_30min <- subset(df, strftime(DateTime, "%M") %in% c('30')) - Kuo-Hsien Chang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接