dez93_2000
dez93_2000

Reputation: 1863

R: IF statement in dplyr::filter requires ELSE otherwise fails?

Per other answers, one can include if statements in pipes and within dplyr functions. However for filter, it seems like one needs to use an else rather than just an if, otherwise the filter will return nothing, calling the error:

no applicable method for 'filter_' applied to an object of class "NULL"

Which is rather misleading IMHO since I'm not using filter_ and am not personally feeding the pipe a NULL class object. Min reprex:

data(mtcars)
a <- 1
mtcars %>% filter(if (a == 1) cyl == 6) # if in filter works
a <- NA
mtcars %>% filter(if (is.na(a)) cyl == 6) # is.na in if in filter works if it evaluates to true
a <- 4
mtcars %>% filter(if (!is.na(a)) cyl == a) # !is.na works if it evaluates to true
a <- NA
mtcars %>% filter(if (!is.na(a)) cyl == a) # doesn't work if it evaluates to false
# Input `..1` must be of size 32 or 1, not size 0.

One can use else to generate an output from the filter, by selecting a filter constraint that will include all results.

mtcars %>% filter(if (!is.na(a)) cyl == a else carb > 0

There's probably a better catch-all filter constraint, and indeed probably a more elegant way of doing this in general, but I couldn't find anyone else having found this problem so if nothing else, hopefully my progress serves its usual purpose.

Any intel as to whether this is a bug, or other ways to approach this, most welcome. Thanks.

Upvotes: 3

Views: 4586

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 388982

We can return TRUE in else condition which will select all the rows in case the condition is FALSE and is not dependent on the value in the column we are testing.

library(dplyr)
a <- NA
mtcars %>% filter(if(!is.na(a)) cyl == a else TRUE)

and to answer your question, yes if would require else part because without it, it would just return NULL which will fail in filter. See this example :

num <- 2
a <- if(num > 1) 'yes'
a
#[1] "yes"
a <- if(num > 3) 'yes'
a
#NULL

Hence when you use

a <- NA
mtcars %>% filter(if(!is.na(a)) cyl == a)

What actually happens is

mtcars %>% filter(NULL)

which returns the same error message.

Upvotes: 8

Related Questions