dplyr 取消引用不适用于过滤器功能

Posted

技术标签:

【中文标题】dplyr 取消引用不适用于过滤器功能【英文标题】:dplyr unquoting does not work with filter function 【发布时间】:2019-06-18 09:39:14 【问题描述】:

也许我遗漏了一些东西,但我似乎无法让 dplyr 的取消引用运算符与过滤器功能一起使用。它适用于选择,但不适用于过滤器......

例子

  set.seed(1234)
  A = matrix(rnorm(100),nrow = 10, ncol = 10)
  colnames(A) <- paste("var", seq(1:10), sep = "")
  varname_test <- "var2"

  A <- as_tibble(A)

  select(A, !!varname_test) #this works as expected

  # this does NOT give me only the rows where var2
  # is positive
  (result1 <- filter(A, !!varname_test > 0))


  # This is how the result 1 should look like
  (result2 <- filter(A, var2 > 0))

  # result1 is not equal to result2

我将不胜感激!

【问题讨论】:

我认为!!select 的情况下实际上并没有做任何事情。不带!! 试试看。对于过滤器,我认为您需要更像filter(A,!!ensym(varname_test) &gt; 0) 您需要ensym()(或其他等效项)将变量名称作为字符串传递给 dplyr 中的大多数函数:filter(A, !! ensym(varname_test) &gt; 0)select() 函数是个例外,它可以将名称作为字符串(以及裸字符串)。 感谢你们@joran 和aosmith!它确实非常有效,如果可以的话,我会将您的任何评论标记为答案:) 我看到我必须深入研究 dplyr 的文档,以更好地了解如何使用取消引用。伙计们干杯! 试试 A %>% filter(var2 >0) 【参考方案1】:

我建议如下:

library(dplyr)   

filter_at(A, vars(starts_with(varname_test)), any_vars(. > 0))

A tibble: 3 x 10
var1   var2   var3   var4   var5   var6     var7   var8   var9  var10
<dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>    <dbl>  <dbl>  <dbl>  <dbl>
1 -2.35  0.0645  0.460 -0.501 -0.281 -1.01  -0.670    0.648 -0.174  1.00 
2  0.429 0.959  -0.694 -1.63  -0.994 -0.162 -0.00760  2.07   0.850 -0.496
3 -0.890 2.42   -0.936 -0.466 -0.497 -1.16   0.336   -0.317 -1.19   2.12 

【讨论】:

@Florian 不知道,感谢您提出新建议 @Jean_N dplyr 和 tidyverse 有一些非常好的工具。以下是它们的概述:dplyr.tidyverse.org/reference/index.html 和带有视觉效果的备忘单,用于 tidyverse 和 dplyr 等。rstudio.com/resources/cheatsheets【参考方案2】:

在这里,我的解决方案 (1g) 使用 filter_ 和使用 paste 建立的条件。 当然,1a 是一个完美的解决方案(正如 joran 和 aosmith 在 cmets 中提供的那样)。

我认为这可能是使用 curly 的好地方,但我无法让它工作(可能不适用?)

我还想:如果我们想通过多个变量进行过滤怎么办?这是您在下面看到 2g 工作的地方(而 2a 不再工作)。

其他问题:filter_ 现在已弃用,我不确定这里的正确语法是什么。将在一个问题中提出这个问题。

library(tidyverse)
set.seed(1234)
A <- matrix(rnorm(30),nrow = 10, ncol = 3) %>% as_tibble() %>% set_names(paste("var", seq(1:3), sep = ""))
varnames_1 <- c("var2")

(expected_result_1 <- filter(A, var2 > 0))
#> # A tibble: 3 x 3
#>     var1   var2   var3
#>    <dbl>  <dbl>  <dbl>
#> 1 -2.35  0.0645  0.460
#> 2  0.429 0.959  -0.694
#> 3 -0.890 2.42   -0.936

(answer_1a <- filter(A,!!ensym(varnames_1) > 0)) # works (thanks joran and aosmith)
#> # A tibble: 3 x 3
#>     var1   var2   var3
#>    <dbl>  <dbl>  <dbl>
#> 1 -2.35  0.0645  0.460
#> 2  0.429 0.959  -0.694
#> 3 -0.890 2.42   -0.936

(answer_1b <- filter_(A, varnames_1 > 0)) # filter_ not doing what I thought it might
#> Warning: filter_() is deprecated. 
#> Please use filter() instead
#> 
#> The 'programming' vignette or the tidyeval book can help you
#> to program with filter() : https://tidyeval.tidyverse.org
#> This warning is displayed once per session.
#> # A tibble: 10 x 3
#>      var1    var2    var3
#>     <dbl>   <dbl>   <dbl>
#>  1 -1.21  -0.477   0.134 
#>  2  0.277 -0.998  -0.491 
#>  3  1.08  -0.776  -0.441 
#>  4 -2.35   0.0645  0.460 
#>  5  0.429  0.959  -0.694 
#>  6  0.506 -0.110  -1.45  
#>  7 -0.575 -0.511   0.575 
#>  8 -0.547 -0.911  -1.02  
#>  9 -0.564 -0.837  -0.0151
#> 10 -0.890  2.42   -0.936

(answer_1c <- filter(A, varnames_1 > 0)) # curly curly not doing what I thought it might
#> # A tibble: 10 x 3
#>      var1    var2    var3
#>     <dbl>   <dbl>   <dbl>
#>  1 -1.21  -0.477   0.134 
#>  2  0.277 -0.998  -0.491 
#>  3  1.08  -0.776  -0.441 
#>  4 -2.35   0.0645  0.460 
#>  5  0.429  0.959  -0.694 
#>  6  0.506 -0.110  -1.45  
#>  7 -0.575 -0.511   0.575 
#>  8 -0.547 -0.911  -1.02  
#>  9 -0.564 -0.837  -0.0151
#> 10 -0.890  2.42   -0.936
(answer_1d <- filter(A, varnames_1 > 0)) # curly curly not doing what I thought it might
#> `arg` must be a symbol

conditions_1 <- paste(varnames_1, "> 0")
(answer_1e <- filter(A, conditions_1)) # does not work
#> Error: Argument 2 filter condition does not evaluate to a logical vector
(answer_1f <- filter(A, conditions_1)) # curly curly not doing what I thought it might
#> Error: Argument 2 filter condition does not evaluate to a logical vector
(answer_1g <- filter_(A, conditions_1)) # works
#> # A tibble: 3 x 3
#>     var1   var2   var3
#>    <dbl>  <dbl>  <dbl>
#> 1 -2.35  0.0645  0.460
#> 2  0.429 0.959  -0.694
#> 3 -0.890 2.42   -0.936

# what if we wanted to filter multiple variables?

varnames_2 <- c("var2", "var3")
(expected_result_2 <- filter(A, var2 > 0 & var3 > 0))
#> # A tibble: 1 x 3
#>    var1   var2  var3
#>   <dbl>  <dbl> <dbl>
#> 1 -2.35 0.0645 0.460

(answer_2a <- filter(A,!!ensym(varnames_2) > 0)) # does not work
#> Only strings can be converted to symbols

conditions_2 <- paste(paste(varnames_2, "> 0"), collapse = " & ")
(answer_2f <- filter(A, conditions_2)) # curly curly not doing what I thought it might
#> Error: Argument 2 filter condition does not evaluate to a logical vector
(answer_2g <- filter_(A, conditions_2)) # works
#> # A tibble: 1 x 3
#>    var1   var2  var3
#>   <dbl>  <dbl> <dbl>
#> 1 -2.35 0.0645 0.460

由reprex package (v0.3.0) 于 2019 年 8 月 28 日创建

【讨论】:

以上是关于dplyr 取消引用不适用于过滤器功能的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用dplyr包聚合(group_by)数据并过滤(fiter)之后再拆开聚合数据(ungroup取消组合)使用ggplot2可视化拆开分组后的线图(line plot)

无法使用 R dplyr 在旧版 SQL 查询中引用 SQL 视图

创建一个函数,该函数通过运算符传递多个参数,用于使用 dplyr 过滤数据集

R Shiny Reactive 值,dplyr 过滤器错误?

过滤器集字段不适用于多个对象

Couchdb 视图不适用于多个过滤器