R 如何将 curly curly 与 filter 或 filter_ 一起使用?
R How to use curly curly with filter or filter_?
我在评论者建议 !!ensym 的地方回答这个 ,我认为这可能是使用 curly curly {{ 的好地方,但我无法让它工作(也许不适用? ).
如果不使用 filter_、eval/parse 或 quote-unquote,我该如何进行过滤操作? ~ 有帮助吗?
我的解决方案 (1g) 使用 filter_ 和条件建立粘贴。
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-08-28 创建
{{
仅适用于 within 函数,带有函数参数。 ensym()
和其他以 en
开头的运算符也是如此。
如果您不在函数中并且变量名称为字符串,则需要 !!sym()
。 sym()
部分将变量名转换为代码对象(符号),!!
部分将其插入到位。
如果paste(paste(varnames_2, "> 0"), collapse = " & ")
是主题。您必须构建过滤器参数。
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
正如 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
我在评论者建议 !!ensym 的地方回答这个
如果不使用 filter_、eval/parse 或 quote-unquote,我该如何进行过滤操作? ~ 有帮助吗?
我的解决方案 (1g) 使用 filter_ 和条件建立粘贴。 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-08-28 创建{{
仅适用于 within 函数,带有函数参数。 ensym()
和其他以 en
开头的运算符也是如此。
如果您不在函数中并且变量名称为字符串,则需要 !!sym()
。 sym()
部分将变量名转换为代码对象(符号),!!
部分将其插入到位。
如果paste(paste(varnames_2, "> 0"), collapse = " & ")
是主题。您必须构建过滤器参数。
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
正如 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