R语言mutate循环中动态变量处理问题求助
处理R中mutate循环生成动态变量的问题
需求说明
现有一个dataframe,需要循环生成tonexti、lefti、total_tonexti系列列:
tonexti= 上一行的tonext(i-1)+ 上一行的left(i-1)- 当前行的left(i-1)lefti= 当前行的valuei-tonextitotal_tonexti=tonexti列的累积和(NA替换为0后)
前3列已生成,需对i=2到4重复上述逻辑,之前尝试eval()、assign()未成功。
尝试的错误代码
for(i in 2:4){ assign("actual_tonext", paste0("tonext", i)) assign("above_tonext", paste0("tonext", i-1)) assign("actual_left", paste0("left", i)) assign("above_left", paste0("left", i-1)) assign("total_tonext", paste0("total_tonext", i)) assign("variable", paste0("value", i)) newdf = final_df %>% mutate( #eval(actual_tonext) = lag(eval(above_tonext)) + lag(eval(above_left)) - eval(above_left), actual_tonext = lag(above_tonext) + lag(above_left) - above_left, actual_left = variable - actual_tonext, total_tonext = cumsum(replace_na(actual_tonext, 0)) ) }
单循环示例(i=2时的正确逻辑)
newdf = final_df %>% mutate( tonext2 = lag(tonext1) + lag(left1) - left1, left2 = value2 - tonext2, total_tonext2 = cumsum(replace_na(tonext2, 0)), )
现有DataFrame示例
| princ | value1 | value2 | tonext1 | left1 | total_tonext1 | tonext2 | left2 | total_tonext2 |
|---|---|---|---|---|---|---|---|---|
| 42 | 42 | NA | NA | NA | 0 | NA | NA | 0 |
| 45 | 45 | 0 | 3 | 42 | 3 | NA | NA | 0 |
| 45 | 45 | 0 | 0 | 45 | 3 | 0 | 0 | 0 |
| 45 | 45 | 0 | 0 | 45 | 3 | 0 | 0 | 0 |
| 221 | 221 | 0 | 176 | 45 | 179 | 0 | 0 | 0 |
| 307 | 307 | 0 | 86 | 221 | 265 | 0 | 0 | 0 |
| 438 | 438 | 0 | 131 | 307 | 39 | 0 | 0 | 0 |
| 438 | 438 | 0 | 0 | 438 | 396 | 0 | 0 | 0 |
| 475 | 475 | 0 | 37 | 438 | 433 | 0 | 0 | 0 |
| 899 | 899 | 0 | 424 | 475 | 85 | 0 | 0 | 0 |
| 910 | 910 | 0 | 11 | 899 | 868 | 0 | 0 | 0 |
| 918 | 732 | 187 | 8 | 724 | 876 | 186 | 1 | 186 |
| 918 | 732 | 187 | 0 | 732 | 876 | 0 | 187 | 186 |
| 1018 | 829 | 190 | 100 | 729 | 976 | 3 | 187 | 189 |
| 1227 | 102 | 207 | 209 | 812 | 1185 | 17 | 190 | 206 |
| 1234 | 102 | 206 | 7 | 1021 | 1192 | 0 | 206 | 206 |
| 1387 | 117 | 208 | 153 | 1026 | 1345 | 2 | 206 | 208 |
| 2495 | 219 | 298 | 1108 | 1083 | 2453 | 96 | 202 | 304 |
| 2495 | 219 | 298 | 0 | 2191 | 2453 | 0 | 298 | 304 |
| 2495 | 218 | 302 | 0 | 2186 | 2453 | 5 | 297 | 309 |
| 2512 | 220 | 302 | 17 | 2186 | 2470 | 0 | 302 | 309 |
正确实现代码
在dplyr中处理动态列名,需要使用.data[[列名字符串]]引用已有列,用!!列名符号 :=定义新列名,代码如下:
# 初始化newdf为原数据 newdf <- final_df # 循环处理i=2到4 for(i in 2:4){ # 定义所有动态列名 actual_tonext <- paste0("tonext", i) above_tonext <- paste0("tonext", i-1) actual_left <- paste0("left", i) above_left <- paste0("left", i-1) total_tonext_col <- paste0("total_tonext", i) variable_col <- paste0("value", i) newdf <- newdf %>% mutate( # 生成tonexti列 !!actual_tonext := lag(.data[[above_tonext]]) + lag(.data[[above_left]]) - .data[[above_left]], # 生成lefti列 !!actual_left := .data[[variable_col]] - .data[[actual_tonext]], # 生成total_tonexti列 !!total_tonext_col := cumsum(replace_na(.data[[actual_tonext]], 0)) ) }
代码说明
.data[[colname]]:dplyr中安全引用字符串格式列名的方式,避免非标准求值的歧义!!colname_sym := value:!!用来展开列名符号,:=允许左边使用动态变量作为新列名,替代普通的=(=左边不能是变量)- 循环中每次更新
newdf,确保后续循环能用上一次生成的新列
内容的提问来源于stack exchange,提问作者More
相关产品推荐
相关产品推荐

