You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"
))

解决方案

原代码存在两个核心问题:

  1. 管道断裂:arrange(Type, Year)后未添加%>%,导致排序结果未传递给后续的group_by,分组基于原始未排序数据。
  2. 全局数据引用: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:47:34