如何使用dplyr计算末行前最后n行的cummean值
问题背景
使用dplyr处理数据框时,需要计算每行之前最后2行的累计均值,以示例数据value = c(1,2,3,4)为例,遍历到值为4的行时,预期计算结果为(2+3)/2 = 2.5。
原有尝试代码如下,无法正常运行:
new_df -> df %>% summarise( roll_mean = cummean(value,-2) )
报错原因
- dplyr内置的
cummean()仅支持计算从首行到当前行的全量累计均值,只接受1个输入参数,不支持传入偏移量自定义计算窗口,传入-2会直接触发参数不匹配报错。 - 原代码使用
summarise()实现行级计算逻辑错误,summarise()会将多行结果折叠为单条汇总值,保留所有行的计算结果需要使用mutate()函数。 - 原代码赋值方向写反,
new_df -> df %>% ...会将空对象new_df赋值给df,覆盖原始数据,正确赋值方向应为new_df <- df %>% ...。 - 需求本质是排除当前行、取前置2个值计算滚动均值,和原生
cummean()的计算逻辑不匹配。
实现方案
方案1:tidyverse生态通用写法(推荐,适配任意窗口长度)
使用tidyverse官方的滚动计算包slider和dplyr搭配,逻辑灵活可扩展:
library(dplyr) library(slider) # 构造示例数据 df <- tibble(value = c(1,2,3,4)) df <- df %>% mutate( roll_mean = slide_dbl( .x = value, .f = ~mean(.x, na.rm = TRUE), .before = 2, # 取当前行之前最多2行数据 .after = -1 # 排除当前行及之后的行 ) )
运行结果如下,完全符合预期:
| value | roll_mean |
|---|---|
| 1 | NA |
| 2 | 1.0 |
| 3 | 1.5 |
| 4 | 2.5 |
如果后续需要调整窗口长度,只需要修改.before参数即可,比如要算之前3行的均值就改成.before = 3。
方案2:无额外依赖写法(固定窗口场景)
如果不想安装其他包,且窗口长度固定为2,可以直接用dplyr的lag()函数取前置位的值计算:
df <- df %>% mutate( roll_mean = (lag(value, 1) + lag(value, 2)) / 2 )
运行结果和方案1完全一致,缺点是窗口长度变化时需要手动调整公式,灵活度较低。
注意事项
- 前几行因为前置数据不足2条,返回
NA属于正常情况,如果需要对边界行做特殊计算,可以在均值函数里补充规则,或者调整slider的.complete参数设置。 - 如果数据存在分组,直接在
mutate()前加group_by()即可,滚动计算会自动在每个分组内独立计算。
内容的提问来源于stack exchange,提问作者Samuel Disorbo
相关产品推荐
相关产品推荐

