求助:用for循环结合sum_run实现多列分组滚动求和报错
批量按分组实现滚动求和的问题
我有一个包含约25个Area、45个不同时间维度变量的dataframe,已通过sum_run实现单列按Area分组的滚动求和,代码如下:
df%>% group_by(Area) %>% mutate(Measure_A_sum = sum_run(`Measure A`, k =4, na_pad = T, lag = 0))
现在想对39至71列批量执行该操作,尝试用for循环实现但持续报错,当前错误为unexpected =错误,我的循环代码如下:
for (col in 39:length(df)) { test <- df %>% group_by(Area) %>% mutate(paste(df[col], ' - Rolling', sep = '') = sum_run(df[col], k = 4, na_pad = T, lag = 0)) }
数据样本:
structure(list(Area = c("A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C", "C", "C"), Quarter = c(2022.1, 2022.2, 2022.3, 2022.4, 2023.1, 2023.2, 2023.3, 2023.4, 2022.1, 2022.2, 2022.3, 2022.4, 2023.1, 2023.2, 2023.3, 2023.4, 2022.1, 2022.2, 2022.3, 2022.4, 2023.1, 2023.2, 2023.3, 2023.4), Year = c(2021L, 2021L, 2021L, 2022L, 2022L, 2022L, 2022L, 2023L, 2021L, 2021L, 2021L, 2022L, 2022L, 2022L, 2022L, 2023L, 2021L, 2021L, 2021L, 2022L, 2022L, 2022L, 2022L, 2023L), `Measure A` = c(3457L, 3348L, 3279L, 3095L, 3155L, NA, NA, NA, 3416L, 3325L, 3248L, 3076L, 3187L, NA, NA, NA, 2815L, 1942L, 1960L, 1863L, 2033L, NA, NA, NA), `Measure B` = c(NA, NA, NA, NA, NA, NA, NA, NA, 168L, 230L, 221L, 253L, 318L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), `Measure C` = c(374L, 408L, 404L, 497L, 455L, NA, NA, NA, 814L, 853L, 711L, 689L, 534L, NA, NA, NA, 1430L, 1335L, 1551L, 1352L, 1512L, NA, NA, NA)), row.names = c(NA, 24L), class = "data.frame")
问题原因及解决方案
错误原因
循环代码的核心问题:
mutate中直接用paste(...) = ...属于语法错误,R不允许在赋值左侧直接用表达式生成变量名,必须用动态变量名赋值方式。df[col]返回的是数据框子集,而sum_run需要向量输入,应该用df[[col]]或dplyr的.datapronoun引用列。- 每次循环重新赋值
test会覆盖之前的结果,需基于上一次的结果持续更新。
正确的For循环实现
# 初始化test为原始数据框 test <- df # 获取目标列的列名(39到71列) target_cols <- colnames(df)[39:length(df)] for (col_name in target_cols) { # 生成新列名 new_col_name <- paste0(col_name, ' - Rolling') # 按分组计算滚动求和并添加新列 test <- test %>% group_by(Area) %>% mutate(!!new_col_name := sum_run(.data[[col_name]], k = 4, na_pad = TRUE, lag = 0)) %>% ungroup() # 取消分组避免后续操作受影响 }
关键语法说明
!!new_col_name :=:!!用于解引用变量名,:=是dplyr中动态赋值的运算符,实现用变量作为新列名。.data[[col_name]]:在dplyr管道中安全引用列名,避免环境变量冲突。- 每次循环基于
test更新,保留之前添加的新列。
更高效的dplyr批量处理方式(无需循环)
推荐用dplyr::across实现批量操作,代码更简洁高效:
test <- df %>% group_by(Area) %>% mutate(across(39:last_col(), # 选择39到最后一列 ~sum_run(.x, k = 4, na_pad = TRUE, lag = 0), .names = "{col} - Rolling")) %>% # 定义新列名格式 ungroup()
优势
- 无需手动循环,代码简洁易读。
- 性能优于for循环,适合大数据集处理。
.names参数直接指定新列名格式,无需额外处理。
内容的提问来源于stack exchange,提问作者user20012036
相关产品推荐
相关产品推荐

