如何在group_by后结合for循环使用mutate并动态命名变量?
分组后在for循环中用mutate动态命名变量的解决方法
错误代码与报错信息
原始尝试的代码:
dat = data.frame(a = c(rep(1,5),rep(2,4),rep(3,7)), b = c(1:16)) for (i in 1:21){ dat %<>% group_by(a) %>% mutate(paste('lag_',i,,sep = '') = lag(b, n = i)) }
运行后报错:
Error: unexpected '=' in:
" dat%<>% group_by(a) %>%
mutate(paste('lag_',i,,sep = '') ="
错误原因
dplyr的mutate不支持直接将字符串(比如paste生成的变量名)用普通等号=赋值,必须使用动态赋值运算符:=,同时需要把字符串形式的变量名转换为dplyr能识别的语法对象。另外你写的paste('lag_',i,,sep = '')多了一个多余的逗号,属于语法小错误。
修正后的代码(for循环版本)
使用!!sym()配合:=实现动态命名,同时修正paste的语法问题:
library(dplyr) library(magrittr) # 加载%<>%运算符的包 dat = data.frame(a = c(rep(1,5),rep(2,4),rep(3,7)), b = c(1:16)) for (i in 1:21){ # 生成变量名,用paste0更简洁 var_name <- paste0('lag_', i) dat %<>% group_by(a) %>% # 用!!sym()把字符串转成符号,用:=赋值 mutate(!!sym(var_name) := lag(b, n = i)) %>% ungroup() # 建议每次循环后取消分组,避免后续操作异常 }
更简洁的tidyverse风格写法(无需for循环)
如果不想用for循环,可以用across配合.names参数直接批量生成滞后变量,代码更简洁高效:
library(dplyr) dat = data.frame(a = c(rep(1,5),rep(2,4),rep(3,7)), b = c(1:16)) dat <- dat %>% group_by(a) %>% # 批量生成1到21阶滞后变量,自动命名为lag_1、lag_2... mutate(across(1:21, ~lag(b, n = .x), .names = "lag_{.x}")) %>% ungroup()
注:因为每个分组的行数最多为7(a=3的组),所以当滞后阶数i>7时,对应组的结果会全为NA,这是正常的逻辑结果。
内容的提问来源于stack exchange,提问作者doraemon
相关产品推荐
相关产品推荐

