在使用非标准评估的函数中,检查列是否存在

Within a function that uses non-standard evaluation, check whether a column exists

我正在尝试将非标准评估与函数一起使用,如果提供的 data.frame 中存在一列,则会发生一组事情,如果存在不同的列,则会发生其他事情。但是,当用户在函数中提供列名时,我不知道如何检查该条件。这是一个例子:

DF1 <- tibble(ColA = 1:4, ColB = 9:12)
DF2 <- tibble(ColA = 1:4, ColC = 5:8)

如果 columnB 存在于用户可能提供的所有 data.frame 中,则此函数将起作用:

myfun1 <- function(DF, columnA, columnB){
      columnA <- enquo(columnA)
      columnB <- enquo(columnB)

      DF %>% mutate(NewColumn = !!columnA * !!columnB)
}

myfun1(DF1, columnA = ColA, columnB = ColB)

并且如果 columnC 始终存在,那么 这个 函数将起作用:

myfun2 <- function(DF, columnA, columnC){
      columnA <- enquo(columnA)
      columnC <- enquo(columnC)

      DF %>% mutate(NewColumn = !!columnA / !!columnC)
}

myfun2(DF2, columnA = ColA, columnC = ColC)

但我真正想要的是一个更灵活的函数,它会检查 columnB 是否是所提供的 data.frame 中的一个列,如果是则执行某些操作,如果不是则执行其他操作。除了我知道 if 语句不正确之外,类似这样的事情:

myFlexibleFun <- function(DF, columnA, columnB, columnC){
      columnA <- enquo(columnA)
      columnB <- enquo(columnB)
      columnC <- enquo(columnC)

      if(exists(!!columnB)){          # I know "exists" isn't the correct syntax, but what is?
            DF %>% mutate(NewColumn = !!columnA * !!columnB)
      } else {
            DF %>% mutate(NewColumn = !!columnA / !!columnC)
      }
}

我尝试了 if(quote(columnB) %in% names(DF)),我尝试了 if(deparse(columnB) %in% names(DF)),但都没有用。

如果

我会喜欢
myFlexibleFun(DF1, columnA = ColA, columnB = ColB)     

还有

myFlexibleFun(DF2, columnA = ColA, columnC = ColC)

都有效。

quote() 不起作用,因为您已经将 columnB 转换为 quosore,因此您需要改用 as_label()

myFlexibleFun <- function(DF, columnA, columnB, columnC){
    columnA <- enquo(columnA)
    columnB <- enquo(columnB)
    columnC <- enquo(columnC)

    if(as_label(columnB) %in% names(DF)){
        DF %>% mutate(NewColumn = !!columnA * !!columnB)
    } else {
        DF %>% mutate(NewColumn = !!columnA / !!columnC)
    }
}

这让你得到你想要的:

myFlexibleFun(DF1, columnA = ColA, columnB = ColB)
#> # A tibble: 4 x 3
#>    ColA  ColB NewColumn
#>   <int> <int>     <int>
#> 1     1     9         9
#> 2     2    10        20
#> 3     3    11        33
#> 4     4    12        48
myFlexibleFun(DF2, columnA = ColA, columnC = ColC)
#> # A tibble: 4 x 3
#>    ColA  ColC NewColumn
#>   <int> <int>     <dbl>
#> 1     1     5     0.2  
#> 2     2     6     0.333
#> 3     3     7     0.429
#> 4     4     8     0.5