1

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

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

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

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)

两者都有效。

4

1 回答 1

2

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
于 2020-05-24T15:06:07.530 回答