我正在使用dplyr
并尝试整洁的评估。我很困惑如何检查以确保有人放入裸对象而不是NSE的字符串。例如,我想过滤非缺失数据:
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
df = data_frame(
myvar = c(rep("yes", 2), NA)
)
myfun <- function(x){
x = enquo(x)
num = df %>%
filter(!is.na( !! x))
return(num)
}
myfun(myvar)
#> # A tibble: 2 x 1
#> myvar
#> <chr>
#> 1 yes
#> 2 yes
如果可能的话,我希望字符串相当于失败。这当前给出“错误”结果,因为is.na("myvar")
永远不会错误。
myfun("myvar") # wrong result
#> # A tibble: 3 x 1
#> myvar
#> <chr>
#> 1 yes
#> 2 yes
#> 3 <NA>
在查看What is the tidyeval way of using dplyr::filter?之后,似乎filter_at
将允许这两种方案正常工作:
myfun <- function(x){
x = enquo(x)
num = df %>%
filter_at(vars( !! x), all_vars(!is.na(.)))
return(num)
}
myfun(myvar)
#> # A tibble: 2 x 1
#> myvar
#> <chr>
#> 1 yes
#> 2 yes
myfun("myvar") # correct result
#> # A tibble: 2 x 1
#> myvar
#> <chr>
#> 1 yes
#> 2 yes
但有没有办法让myfun("myvar")
失败?除非使用colnames()
,否则我无法使用as.name
和if语句作为未加引号的表达式失败。
答案 0 :(得分:3)
您可以使用类似
的字符串测试字符串文字myfun <- function(x){
x = enquo(x)
stopifnot(!is.character(rlang::f_rhs(x)))
num = df %>%
filter(!is.na( !! x))
return(num)
}
由于quosures与公式非常相似,rlang::f_rhs
部分提取传入的“thing”,因此您可以检查它是什么类型的语言元素。也许不是检查一个字符串,你可能只想确保它是一个符号。你可以用
myfun <- function(x){
x = enquo(x)
stopifnot(rlang::quo_is_symbol(x))
num = df %>%
filter(!is.na( !! x))
return(num)
}
然后这些做你想做的事情
myfun(myvar) #works
myfun("myvar") #error
答案 1 :(得分:0)
在取消引用之前,您可以在函数中测试if
。如果您将x
作为带引号的字符串传递,则其长度= 1,函数将返回x
或您想要的任何失败条件。如果您(正确地)传入了一个不带引号的变量名,那么NA
将失败(使用length
)但错误将被Error: object 'knockdown' not found
静音,并且该函数将正常进行。
try()