R语言用zoo和dplyr按组计算滚动加权均值的问题
按组计算移动加权平均的R语言问题解决
问题背景
需要在R中按Type分组计算移动加权平均,原代码如下:
df %>% arrange(Type, Year) group_by(Type) %>% mutate( "weighted.rolling.mean" = rollapplyr( df %>% select(Value, Area), width = 50, function(z){ return( weighted_mean = weighted.mean(z[,"Value"],z[,"Area"], partial = TRUE) ) }, by.column = FALSE, align = "right", fill=NA ) )
未使用group_by时代码运行正常,但添加分组后出现错误。
错误信息
Error in `mutate()`: ℹ In argument: `weighted.rolling.mean = rollapplyr(...)`. ℹ In group 1: `Type = "Etageadskillelse"`. Caused by error in `x * w`: ! non-numeric argument to binary operator Backtrace: 1. ... %>% ... 9. zoo::rollapplyr(...) 11. zoo:::rollapply.default(..., align = align) 14. zoo:::rollapply.zoo(zoo(data), ...) 15. base::mapply(...) 16. zoo (local) `<fn>`(dots[[1L]][[50L]], dots[[2L]][[50L]], data = `<chr[,4]>`) 17. FUN(data[posns, ], ...) 19. stats:::weighted.mean.default(z[, "Value"], z[, "Area"], partial = TRUE)
数据集示例
structure(list(Value = c(0.55, 0.14, 0.760367571281347, 0.25, 0.4, 0.12, 0.4, 0.13, 0.14, 0.344161801501251, 1.06, 0.58, 0.45, 0.68, 0.36, 0.19, 0.25, 0.68, 0.08, 0.14, 1.74386666666667, 0.3, 0.350285714285714, 0.07, 0.14), Area = c(3.5, 11.2, 87.33, 133, 16.67, 112.3, 44, 281, 121, 119.9, 77, 82, 33.48, 102.1, 98.07, 121.53, 54, 2.15, 15.48, 136, 30, 31.5, 70, 144.15, 100), Type = c("Ydervæg", "Kvist", "Ydervæg", "Ydervæg", "Ydervæg", "Loft", "Skunk", "Loft", "Loft", "Ydervæg", "Ydervæg", "Etageadskillelse", "Terrændæk", "Ydervæg", "Ydervæg", "Loft", "Loft", "Ydervæg", "Terrændæk", "Loft", "Etageadskillelse", "Terrændæk", "Skunk", "Terrændæk", "Loft"), Year = c(1965L, 2011L, 1966L, 1929L, 1890L, 1937L, 1926L, 1846L, 1965L, 1920L, 1963L, 1936L, 1947L, 1920L, 1973L, 1967L, 1915L, 1814L, 1964L, 2005L, 1950L, 1933L, 1929L, 1874L, 1964L )), row.names = c(NA, -25L), class = c("tbl_df", "tbl", "data.frame" ))
解决方案
原代码存在两个核心问题:
- 管道断裂:
arrange(Type, Year)后未添加%>%,导致排序结果未传递给后续的group_by,分组基于原始未排序数据。 - 全局数据引用:
rollapplyr中使用df %>% select(Value, Area)调用了整个数据集,而非当前分组的子集,导致分组内计算时混入其他组数据,引发类型错误。
修正后的代码如下:
library(dplyr) library(zoo) df %>% arrange(Type, Year) %>% # 修复管道连接 group_by(Type) %>% mutate( weighted.rolling.mean = rollapplyr( select(Value, Area), # 使用当前分组的子集数据 width = 50, function(z) { weighted.mean(z[["Value"]], z[["Area"]], partial = TRUE) # 简化写法,直接返回结果 }, by.column = FALSE, align = "right", fill = NA ) ) %>% ungroup() # 可选:取消分组恢复普通数据框
关键改动说明
- 修复管道:确保排序后的数据能传递到分组步骤。
- 替换输入:
select(Value, Area)在分组上下文中自动选取当前组的Value和Area列,避免全局数据干扰。 - 简化函数:去掉冗余的
return赋值,直接返回weighted.mean计算结果,代码更简洁。
运行修正后的代码即可按组正确计算移动加权平均。
内容的提问来源于stack exchange,提问作者KurtRavn
相关产品推荐
相关产品推荐

