使用mutate和ifelse循环变量名的R函数

hgqdbh6s  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(135)

我有一个包含多个变量的 Dataframe ,我将变量分为三类,第一类是变量列表,我将其称为case 1变量,第二类是变量列表,我将其称为case 2变量,第一类和第二类列表的长度相同(称为长度k),且情况1列表第i个元素与情况2列表的第i个元素具有相同的类。告诉我应该应用哪种情况的变量。
我想做的是从i = 1到k循环,并创建k个新变量,其中第i个变量成为第一个列表的第i个元素,如果其中= 1,则成为第二个列表的第i个元素,如果其中= NA(或任何其他值),则新列表的第i个变量为NA。我希望它对第i个元素是字符串、数字还是当然,我不想在代码中手动输入变量列表。
我已经提出了一个使用get()的解决方案,但是,我想知道是否有更好的方法来做到这一点和/或使用get()是否有潜在的陷阱。

rm(list = ls())

library(dplyr)

case <- c(1, 2, 2, 1, 2, 1, 1, NA, 2, 1)
v1A <- c(45, 55, 65, 75, 85, 95, 105, 115, 125, 135)
v2A <- c(-45, -55, -65, -75, -85, -95, -105, -115, -125, -135)
v1B <- c("a","b","c","d","e","f","g","h","i","j")
v2B <- c("z","y","x","w","v","u","t","s","r","q")
df <- data.frame(which_case = case, var1A = v1A, var2A = v2A, var1B = v1B, var2B = v2B)

newvar <- c("varA","varB")
var1 <- c("var1A","var1B")
var2 <- c("var2A","var2B")

# test whether TRUE (and returns FALSE if FALSE OR NA):
is_true <- function(x) { return(x==TRUE & !is.na(x)) }
# test whether FALSE (and return FALSE if TRUE OR NA):
is_false <-function(x) { return(x==FALSE & !is.na(x)) }

for (i in 1:length(newvar)) {
  newvar_i = newvar[i]
  var1_i = var1[i]
  var2_i = var2[i]
  df <- df %>% mutate({{newvar_i}} := NA)
  df <- df %>% mutate({{newvar_i}} := ifelse(is_true(which_case==1), get(var1_i), get(newvar_i)))
  df <- df %>% mutate({{newvar_i}} := ifelse(is_true(which_case==2), get(var2_i), get(newvar_i)))
  #df <- df %>% mutate(!!newvar_i := get(var1_i))
}

print(df)

   which_case var1A var2A var1B var2B varA varB
1           1    45   -45     a     z   45    a
2           2    55   -55     b     y  -55    y
3           2    65   -65     c     x  -65    x
4           1    75   -75     d     w   75    d
5           2    85   -85     e     v  -85    v
6           1    95   -95     f     u   95    f
7           1   105  -105     g     t  105    g
8          NA   115  -115     h     s   NA <NA>
9           2   125  -125     i     r -125    r
10          1   135  -135     j     q  135    j
y0u0uwnf

y0u0uwnf1#

df_orig <- data.frame(
  stringsAsFactors = FALSE,
  which_case = c(1, 2, 2, 1, 2, 1, 1, NA, 2, 1),
  var1A = c(45, 55, 65, 75, 85, 95, 105, 115, 125, 135),
  var2A = c(-45, -55, -65, -75, -85, -95, -105, -115, -125, -135),
  var1B = c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
  var2B = c("z", "y", "x", "w", "v", "u", "t", "s", "r", "q")
)

newvar <- c("varA", "varB")
var1 <- c("var1A", "var1B")
var2 <- c("var2A", "var2B")

library(dplyr)
library(rlang)
library(purrr)

c_build <- function(v1, v2) {
  force(v1)
  force(v2)
  \(x){
    vv1 <- eval(ensym(v1), envir = caller_env())
    vv2 <- eval(ensym(v2), envir = caller_env())
    case_match(
      x,
      1 ~ vv1,
      2 ~ vv2
    )
  }
}
mbuild <- function(n) {
  imap(
    n,
    \(n, y){
      c_build(
        var1[[y]],
        var2[[y]]
      )
    }
  ) |> set_names(n)
}
myfuncs <- mbuild(newvar)

df2 <- df_orig |> mutate(across(which_case, 
                                myfuncs, 
                                .names = "{.fn}"))

相关问题