0

I'm trying to pass in a conditional (<,>, etc) and a value into a function to be evaluated in a dplyr filter.

Other answers on SO suggest I should simply be able to use parse, but my sample function (without using the args) fails with:

Error in (...) & ~parse(text = "obj_200 > 0") : operations are possible only for numeric, logical or complex types

Sample function:

filterOrder = function( df, cond, value) {
  df = df %>% 
    rownames_to_column('date') %>%
    filter( ...
            parse(text="obj_200 > 0"),                       
            ...                    
          ) 
  ...
  
  return(df)
}
Ian
  • 1,507
  • 3
  • 21
  • 36
  • try: `eval(parse(text="obj_200 > 0"))`. Not sure will it work in `dplyr` but it works in `data.table` for sure. Also note that from you question its not obvious at all should you even use this syntax, why not just use `obj_200 > 0`? – det Jul 12 '20 at 17:07
  • @det Looks like the eval() was what was needed. Thanks. Can you explain /why/ that's needed here? (ps. for this example, substitution is not needed: just wanted to get the basics working before substituting cond and value!) – Ian Jul 12 '20 at 17:57
  • think you can find here answer: https://stackoverflow.com/questions/1743698/evaluate-expression-given-as-a-string – det Jul 12 '20 at 18:08

2 Answers2

2

We can use parse_expr from rlang

filterOrder = function( df, cond, value) {
   df %>% 
       rownames_to_column('date') %>%
       filter(!!(rlang::parse_expr("obj_200 > 0")))
      }

A reproducible example with iris

data(iris)
iris %>%
        filter(!!(rlang::parse_expr('Species == "setosa"')))
akrun
  • 874,273
  • 37
  • 540
  • 662
1

if you want to get rid of the string-conditions, you could do something like that

library(magrittr)

df <- dplyr::tibble(A=1:10,
                    B=11:20,
                    C=10:1)

foo <- function(df, .cond){
  .cond <- rlang::enquo(.cond)      
  res <- df %>%
    dplyr::filter(!!.cond)      
  return(res)
}

foo(df,.cond=A>5)

# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     6    16     5
2     7    17     4
3     8    18     3
4     9    19     2
5    10    20     1

foo(df,.cond=A==1)

# A tibble: 1 x 3
      A     B     C
  <int> <int> <int>
1     1    11    10

foo(df,.cond=A>3 & C<4)

# A tibble: 3 x 3
      A     B     C
  <int> <int> <int>
1     8    18     3
2     9    19     2
3    10    20     1
sambold
  • 807
  • 5
  • 15