【问题标题】:Dynamic variable names to mutate variables in for-loop动态变量名称以在 for 循环中改变变量
【发布时间】:2021-11-18 02:48:46
【问题描述】:

我在 for 循环中创建动态变量名时遇到问题。我参考了以前关于这个主题的 stackoverflow 帖子,我正在复制谁的代码,但在我的情况下不起作用。我正在重新编码对调查的响应以考虑跳过逻辑,并尝试使用以下代码更有效地重新编码这些代码,而不是一个一个地重新编码。如果您有任何建议,请告诉我。

# Example data:
var0 = c(1, 2, 2, 1, 1, 2, 2)
var1 = c(NA, 1, 0, 1, 0, NA, 4444)
var2 = c(1, NA, 0, 0, 1, 4444, NA)
var3 = c(NA, 1, 0, 4444, 1, NA, 1)

df1 <- data.frame(var0, var1, var2, var3)

# Data:
  var0 var1 var2 var3
1    1   NA    1   NA
2    2    1   NA    1
3    2    0    0    0
4    1    1    0 4444
5    1    0    1    1
6    2   NA 4444    0
7    2 4444   NA    1

这是我的函数和 for 循环:

vars = c("var1", "var2")

func <- function(i) {
  mutate(df1, !!i := case_when(!is.na(i) ~ i,
                             is.na(i) & var0 != '1' ~ '4444',
                             TRUE ~ '0'))
}

for(i in vars) {
  df2 <- func(i)
}

test <- df2 %>%
  select(var1, var3) #leaving var3 unchanged to test in comparison

这就是我想要的结果:

  var0 var1 var2 var3
1    1    0    1   NA
2    2    1 4444    1
3    2    0    0    0
4    1    1    0 4444
5    1    0    1    1
6    2 4444 4444   NA
7    1 4444    0    1

【问题讨论】:

    标签: r for-loop variables dynamic


    【解决方案1】:

    当我们传递字符串时,转换为symbol 并计算 (!!)

    func <- function(i) {
       
       mutate(df1, !!i := case_when(!is.na(!! rlang::ensym(i)) ~ as.character(!! rlang::ensym(i)),
                                  is.na(!!rlang::ensym(i)) & var0 != '1' ~ '4444',
                                  TRUE ~ '0'))
     }
    
    

    -测试

    for(i in vars) {
       df1 <- func(i)
     }
    df1
      var0 var1 var2 var3
    1    1    0    1   NA
    2    2    1 4444    1
    3    2    0    0    0
    4    1    1    0 4444
    5    1    0    1    1
    6    2 4444 4444   NA
    7    2 4444 4444    1  
    

    我们也可以使用across 来做这件事

    df1 %>%
        mutate(across(all_of(vars), 
        ~ case_when(!is.na(.) ~ as.character(.), 
           is.na(.) & var0 != '1' ~ '4444', TRUE ~ '0')))
      var0 var1 var2 var3
    1    1    0    1   NA
    2    2    1 4444    1
    3    2    0    0    0
    4    1    1    0 4444
    5    1    0    1    1
    6    2 4444 4444   NA
    7    2 4444 4444    1
    

    【讨论】:

      【解决方案2】:

      当将列名作为字符串传递时,您可以使用.data。同时更新原始变量 (df1) 而不是创建新变量 (df2),因为在函数中您始终引用原始变量 (df1)。

      library(dplyr)
      
      func <- function(i) {
        mutate(df1, !!i := case_when(!is.na(.data[[i]]) ~ .data[[i]],
                                     is.na(.data[[i]]) & var0 != 1 ~ 4444,
                                     TRUE ~ 0))
      }
      
      vars = c("var1", "var2")
      
      for(i in vars) {
        df1 <- func(i)
      }
      
      df1
      
      #  var0 var1 var2 var3
      #1    1    0    1   NA
      #2    2    1 4444    1
      #3    2    0    0    0
      #4    1    1    0 4444
      #5    1    0    1    1
      #6    2 4444 4444   NA
      #7    2 4444 4444    1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多