R如何使用带有过滤器或过滤器_的卷曲卷曲?

Posted

技术标签:

【中文标题】R如何使用带有过滤器或过滤器_的卷曲卷曲?【英文标题】:R How to use curly curly with filter or filter_? 【发布时间】:2020-01-02 06:47:27 【问题描述】:

我正在回答这个question 评论者建议!!ensym,我认为这可能是使用 curly curly 但我无法让它工作(可能不适用?)的好地方。

在不使用 filter_、eval/parse 或 quote-unquote 的情况下,我如何执行此过滤操作? ~ 有帮助吗?

我的解决方案 (1g) 使用 filter_ 和使用 paste 建立的条件。 1a 有效(但它可以以某种方式使用 吗?)

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

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 日创建

【问题讨论】:

【参考方案1】:

仅适用于within 函数,带有函数参数。 ensym() 和其他以 en 开头的运算符也是如此。

如果你不在函数中并且你有字符串形式的变量名,你需要!!sym()sym() 部分将变量名转换为代码对象(符号),!! 部分将其插入到位。

【讨论】:

【参考方案2】:

如果paste(paste(varnames_2, "&gt; 0"), collapse = " &amp; ") 是主要问题。您必须构建过滤器参数。

library(tidyverse)
library(rlang)

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

# with variables as arguments
filter_gt0 <- function(d, ...) 
  conds <- ensyms(...)
  conds <- map(conds, ~quo(!!.x > 0))  
  d %>%
    filter(!!!conds)

A %>%
  filter_gt0(var2, var3)
# # A tibble: 1 x 3
# var1   var2  var3
# <dbl>  <dbl> <dbl>
#   1 -2.35 0.0645 0.460

# or with variables as input
conds <- quos(var2, var3)
filter_gt0_2 <- function(d, conds) 
  conds <- map(conds, ~quo(!!.x > 0))  
  d %>%
    filter(!!!conds)

A %>%
  filter_gt0_2(conds)
# # A tibble: 1 x 3
# var1   var2  var3
# <dbl>  <dbl> <dbl>
#   1 -2.35 0.0645 0.460

【讨论】:

【参考方案3】:

正如 Lionel 指出的,curly-curly 在函数内部起作用。要将它与filter 一起使用,您必须将调用包装在一个函数中。

f <- function(.df, v)  
  filter(.df,  v  > 0) 


# Curly-curly provides automatic NSE support
f( A, var2 )
# # 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

# Strings have to be first converted to symbols
f( A, !!sym("var3") )
# # A tibble: 3 x 3
#     var1    var2  var3
#    <dbl>   <dbl> <dbl>
# 1 -1.21  -0.477  0.134
# 2 -2.35   0.0645 0.460
# 3 -0.575 -0.511  0.575

Curly-curly 旨在引用单个参数。您可以在purrr::reduce 的帮助下通过顺序应用程序将其扩展为使用多个变量。 (别忘了先把你的字符串转换成实际的变量名!):

syms(varnames_2) %>% reduce(f, .init=A)
# # A tibble: 1 x 3
#    var1   var2  var3
#   <dbl>  <dbl> <dbl>
# 1 -2.35 0.0645 0.460

【讨论】:

以上是关于R如何使用带有过滤器或过滤器_的卷曲卷曲?的主要内容,如果未能解决你的问题,请参考以下文章

卷曲参数数组不起作用

如何在 Modal Segue 的过渡中添加完整的卷曲效果?

如何卷曲/折叠 UIView 的底角

使用SSO用户/通行证卷曲

使用postFrom或POST将代码卷曲到R.

如何在 Node.js 中进行远程 REST 调用?任何卷曲?