4

我正在使用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")它绝不是 FALSE。

myfun("myvar") # wrong result
#> # A tibble: 3 x 1
#>   myvar
#>   <chr>
#> 1 yes  
#> 2 yes  
#> 3 <NA>

在查看了使用 dplyr::filter 的 tidyeval 方式是什么之后?,似乎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()and if 语句作为未引用的表达式,除非使用as.name.

4

2 回答 2

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部分提取了传入的“事物”,因此您可以检查它是哪种语言元素。也许不是检查字符串,您可能只想确保它是一个符号。你可以这样做

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
于 2018-03-29T18:48:05.893 回答
0

您可以x在取消引用之前在您的函数中进行测试。如果您x作为带引号的字符串传入,那么它的长度 = 1 并且函数将返回NA或您想要的任何失败条件。如果您(正确地)传入一个不带引号的变量名,那么length将失败(使用Error: object 'knockdown' not found)但错误将被消除try()并且函数将正常进行。

myfun <- function(x){
try({if (length(x) == 1) return(NA)}, silent = TRUE)
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")
[1] NA
于 2018-03-29T17:51:20.947 回答