R How to use curly curly with filter or filter_?

{{ only works within functions, with function arguments. Same for ensym() and other operators starting with en by the way.

If you're not in a function and you have variable names as strings, you need !!sym(). The sym() part transforms the variable name to a code object (a symbol), and the !! part insert it in place.


As Lionel points out, curly-curly works inside functions. To use it with filter, you thus have to wrap the call inside a function.

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 is meant to reference a single argument. You can extend it to work with multiple variables through sequential application with the help of purrr::reduce. (Don't forget to convert your strings into actual variable names first!):

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

If the paste(paste(varnames_2, "> 0"), collapse = " & ") is the main question. You have to build the filter arguments.

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