在R语言中按日期列计算可指定前置天数的滚动平均值
解决滚动时间窗口平均值计算的问题
嘿,我懂你要做的事了——针对每个分组(比如Name列),在指定的StartDate到EndDate范围内,滚动计算当前日期之前N天(比如你说的4天,含当天)的Values平均值,之前用tapply没得到正确结果,问题出在tapply的逻辑是按日期分组取尾部值的平均,完全没处理时间窗口的滚动和起止日期的限制,咱们换个思路来实现:
第一步:先确保日期格式正确
首先得把所有日期列转成R的Date类型,不然时间计算会乱掉:
library(lubridate) # 假设你的日期是月/日/年格式,用mdy转换;如果是年-月-日就用ymd df$DATE <- mdy(df$DATE) df$StartDate <- mdy(df$StartDate) df$EndDate <- mdy(df$EndDate)
第二步:用dplyr + slider实现灵活的滚动窗口计算
推荐用slider包,它对时间窗口的处理非常直观,配合dplyr分组操作,完美匹配你的需求:
library(dplyr) library(slider) # 按Name分组,过滤时间范围,滚动计算平均值 result_df <- df %>% group_by(Name) %>% # 只保留StartDate到EndDate之间的记录 filter(DATE >= StartDate & DATE <= EndDate) %>% # 务必按日期排序,保证滚动顺序正确 arrange(DATE) %>% # 滚动窗口:当前行及之前3条(总共4天),不足4天也计算平均值 mutate(Average = slide_dbl(Values, mean, .before = 3, .complete = FALSE)) %>% ungroup()
.before = 3:表示取当前日期之前的3条记录,加上当前行就是4天的窗口;如果要算“前置4天(不含当天)”,就改成.before = 4, .after = -1.complete = FALSE:允许窗口不足4条时计算平均值(比如前3天);如果要求必须满4天才计算,改成.complete = TRUE即可
备选方案:用zoo包实现滚动平均
如果你不想装新包,用经典的zoo包也能实现,用rollapply支持部分窗口计算:
library(zoo) result_df <- df %>% group_by(Name) %>% filter(DATE >= StartDate & DATE <= EndDate) %>% arrange(DATE) %>% # k=4是窗口大小,align="right"表示以当前行为窗口末尾,partial=TRUE允许不足4条计算 mutate(Average = rollapply(Values, width = 4, FUN = mean, align = "right", partial = TRUE)) %>% ungroup()
为什么之前的tapply不对?
你之前的代码tapply(df$Boe, df$ShutinDate, function(x) mean(tail(sort(x), 5)))是把同一个ShutinDate下的所有Boe值排序后取最后5个的平均,这是按日期分组的聚合,不是跨日期的滚动窗口计算,完全不符合你要的“从StartDate开始,每天滚动算前4天平均值”的需求,所以结果不对。
示例输出(模拟数据)
假设你的数据是这样的:
| Name | DATE | Values | StartDate | EndDate |
|---|---|---|---|---|
| TestA | 2017-03-03 | 50 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-04 | 75 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-05 | 25 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-06 | 30 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-07 | 40 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-08 | 60 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-09 | 80 | 2017-03-05 | 2017-03-10 |
| TestA | 2017-03-10 | 20 | 2017-03-05 | 2017-03-10 |
处理后的Average列会是:
| DATE | Average |
|---|---|
| 2017-03-05 | 25.00 |
| 2017-03-06 | 27.50 |
| 2017-03-07 | 31.67 |
| 2017-03-08 | 38.75 |
| 2017-03-09 | 52.50 |
| 2017-03-10 | 50.00 |
内容的提问来源于stack exchange,提问作者RLW
相关产品推荐
相关产品推荐

