在使用非标准评估的函数中,检查列是否存在
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
我正在尝试将非标准评估与函数一起使用,如果提供的 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