0

I want to create a conjunction expression from a char vector. i.e. given a vector like c("a", "b", "c"). Ultimately I want to pass it to dplyr::filter

Here is my attempt:

makeNonNAConjunctionExpr = function(predictors) {
    # Given a char vector c("a", "b", "c") this function returns an expression:
    # ~!is.na(a) & !is.na(b) & !is.na(c)
    f = function(init, i) {
        i_name = as.name(i); 
        if(is.null(init) || length(init) == 0) {
            return(expr(!is.na(!!i_name))) 
        }
        init = if(is_call(init)) {
                    init
                } else {
                    expr(!!as.name(init))
                }
        e = expr(!is.na(!!init) & !is.na(!!i_name)); 
        return(e)
    }
    ex = Reduce(f, predictors[1], predictors[-1])
    return(quo(ex)) # Return a quosure for dplyr.
}

> x = data.frame(a=c(1,NA, 2), b = c(10, 12, NA), c = c(NA, 90, 100))

> e = makeNonNAConjunctionExpr(c("a", "b"))
> e
<quosure: local>
~!is.na(b) & !is.na(a)
> a %>% dplyr::filter(!!e)
  a  b  c
1 1 10 NA

There has to be an easier way in R to create such expressions from strings, but I could not find any. Any suggestions?

alistaire
  • 42,459
  • 4
  • 77
  • 117
Sid
  • 420
  • 1
  • 6
  • 11
  • 3
    `x %>% filter_at(vars(a, b), all_vars(!is.na(.)))` or better, `x %>% tidyr::drop_na(a:b)` – alistaire Sep 11 '17 at 01:22
  • I think alistaire has nailed it. Just because you can make a series of `!is.na(...)` expressions, doesn't mean you should. Many R functions work on chunks of objects or vectorised comparisons and there is often a way to avoid writing out `if (...) then, else if (...) then` or `condition & condition & condition`. – thelatemail Sep 11 '17 at 02:57
  • @alistaire, can you please upgrade your comment to an answer, so it can upvoted and accepted? – Artem Sokolov Nov 03 '18 at 21:23

0 Answers0