Lazy eval, dplyr "filter" and NAs

644 views Asked by At

I am having some silly problem using lazy evaluation and dplyr. I'm trying to filter some NAs and don't know why the lazyeval version doesn't work. Probably I'm missing something, but I can't find it. Is that so, or is it a bug?

Here is a minimum reproducible example:

library(dplyr)
library(lazyeval)

data(iris)
iris$t <- c(1:140, rep(NA, 10))

#This Works
temp <- filter(iris, !is.na(t))

#This doesn't
temp <- filter_(iris, interp(~(!is.na(x)), x="t"))

Both codes run without throwing out an error.

2

There are 2 answers

1
Rich Scriven On BEST ANSWER

You need to pass "t" as a name.

interp(~(!is.na(x)), x = as.name("t"))
# ~!is.na(t)

As your code stands, you are inserting "t" into is.na() to make is.na("t"), which is FALSE every time. And negating that gives TRUE every time, hence all rows.

interp(~(!is.na(x)), x = "t")
# ~!is.na("t")
0
alistaire On

dplyr has switched over its NSE system from lazyeval to rlang (documented here), deprecating the *_ functions in favor of a new syntax:

library(dplyr)

data(iris)
iris <- iris %>% mutate(t = c(1, rep(NA, 149)))

# normal NSE
iris %>% filter(!is.na(t))
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species t
#> 1          5.1         3.5          1.4         0.2  setosa 1

# string-based SE; use `rlang::sym` to convert to quosure and !! to unquote
x <- "t"
iris %>% filter(!is.na(!!rlang::sym(x)))
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species t
#> 1          5.1         3.5          1.4         0.2  setosa 1

# program your own NSE with `quo` and friends
x <- quo(t)
iris %>% filter(!is.na(!!x))
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species t
#> 1          5.1         3.5          1.4         0.2  setosa 1

# both versions work across the tidyverse
iris %>% tidyr::drop_na(!!x)
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species t
#> 1          5.1         3.5          1.4         0.2  setosa 1

# though tidyr::drop_na is happy with strings anyway
iris %>% tidyr::drop_na("t")
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species t
#> 1          5.1         3.5          1.4         0.2  setosa 1