Eri Kakoki
Eri Kakoki

Reputation: 15

Getting error: Error in UseMethod("filter") : no applicable method for 'filter' applied to an object of class "logical"

I'm so confused because I thought that a logical expression is one of the parameters of a filter() function? Here is my code:

simplifyList <- function(x) {
    x <- x %>% {
        filter(x$Q26 == "Yes")
    }
}
simplifyList(a)

I've checked to make sure a is of the class data.frame, and adding dplyr:: in front of filter() didn't do anything. I even updated the dplyr package in case that was the problem. Is there something I'm missing?

Upvotes: 1

Views: 14977

Answers (4)

Hong Ooi
Hong Ooi

Reputation: 57696

This is because you used braces {} in the right-hand side of your piped expression

x <- x %>% { ... }

and you referred directly to your dataset x in the filter expression

filter(x$Q26 == "Yes")

Both of these are most likely incorrect. For the first one, see the help for %>%:

Using lambda expressions with %>%

Each rhs is essentially a one-expression body of a unary function. Therefore defining lambdas in magrittr is very natural, and as the definitions of regular functions: if more than a single expression is needed one encloses the body in a pair of braces, { rhs }. However, note that within braces there are no "first-argument rule": it will be exactly like writing a unary function where the argument name is "." (the dot).

So instead of x %>% { <expression referring to x> }, something like

x <- x %>% { filter(.$Q26 == "Yes" }

would work. Or you could remove the braces and write

x <- x %>% filter(x$Q26 == "Yes")

and that would also work. But what you REALLY want to do is

x <- x %>% filter(Q26 == "Yes")

or simply

x <- filter(x, Q26 == "Yes")

which avoids any issues to do with piping.

Upvotes: 1

Alexandre Courtiol
Alexandre Courtiol

Reputation: 71

You could make what you wrote work if you use the {} signs at the right locations:

library(dplyr)

a <- data.frame(x = 1:2, Q26 = c("Yes","No"))

simplifyList <- function(x) {
  x <- x %>% 
    filter({{x}}$Q26 == "Yes")
  x
}

simplifyList(a)
#>   x Q26
#> 1 1 Yes

but I would not recommend you to use such unusual syntax. Instead, I would either do this:

simplifyList <- function(x) {
  x %>%
    filter(Q26 == "Yes")
}

simplifyList(a)
#>   x Q26
#> 1 1 Yes

or that:

simplifyList <- function(x) {
  filter(.data = x, Q26 == "Yes")
}

simplifyList(a)
#>   x Q26
#> 1 1 Yes

I hope this helps…

Created on 2021-04-25 by the reprex package (v2.0.0)

Upvotes: 1

Ben Bolker
Ben Bolker

Reputation: 226766

I haven't yet figured out why, but the problem is that you should use Q26 == "Yes" rather than x$Q26 == "Yes":

library(dplyr)
dd <- data.frame(x=1:2, Q26=c("Yes","No"))
simplifyList <- function(x) { x <- x %>% filter(Q26=="Yes") ; return(x) }
simplifyList(dd)

It's far from obvious (to me) why x$Q26 doesn't work - it must have to do with tidyverse's particular evaluation rules, or their interaction with evaluation of function arguments:

  • with(dd, identical(dd$Q26, Q26)) — which is how I would think to mimic tidyverse's rules — is TRUE.
  • dd %>% filter(dd$Q26 == "Yes") works outside of a function ...

Upvotes: 1

s_pike
s_pike

Reputation: 2123

It's a little hard to fully diagnose without example data, but try:

simplifyList <- function(x) {
    x %>%
        filter(Q26 == "Yes")
}
simplifyList(a)

Upvotes: 1

Related Questions