5

I'm struggling to pipe stuff to another argument inside the function filter from dplyr using %>% margritr.

I would assume that this should work:

library(dplyr)
library(margritr)

d <- data.frame(a=c(1,2,3),b=c(4,5,6))
c(2,2) %>% filter(d, a %in% .)

But I get this:

# Error in UseMethod("filter_") : 
#  no applicable method for 'filter_' applied to an object of class "c('double', 'numeric')"

I would expect it to work in the same way as this:

filter(d, a %in% c(2,2))
#   a b
# 1 2 5

What am I doing wrong?

Bruno
  • 115
  • 1
  • 9
  • 2
    I think it's how the pipe was designed, i.e., it passes the previous output to the first argument of the next function. You will probably need to be more explicit, such as `c(2,2) %>% filter(.data = d, etc...` – David Arenburg Oct 13 '17 at 11:10
  • 1
    How about you try this instead `d%>%filter(a %in% c(2,2))` – Kay Oct 14 '17 at 02:06
  • I know that `d%>%filter(a %in% c(2,2))` works. But I'm showing a toy example, in reality my c(2,2) is much more complex and it's output of some other stuff. And that's what I want to pipe. – Bruno Oct 14 '17 at 11:58
  • 2
    If it's more complicated, why not try an inner join instead? data.frame(a = c(2,2)) %>% inner_join(d, by = "a") – David Klotz Oct 14 '17 at 17:26
  • Right, or a semi_join for that matter. Remember, semi_join and anti_join are filtering joins and are much faster than %in%. – Zafar Oct 15 '17 at 13:51

2 Answers2

8

The pipe is designed to compose the function around its first argument when you pass it. When you want to circumvent this behavior, you can generate an anonymous environment that is more flexible. You do this with curly braces, just like when you're writing a function.

5 %>% 
  {filter(iris, Sepal.Length == .)}

For why this works, writing {somefunctions(x, y)} is equivalent to writing function(...) {somefunctions(x, y)}. So the function above ignores its arguments, but just evaluates the variables in its environment. The . pronoun is defined for it by the pipe, and it searches for other variables (like iris) in the global environment.

Brian
  • 7,900
  • 1
  • 27
  • 41
0

By default it will pipe to the first argument. The only way around it is to name the first arg explicitly:

c(2,2) %>% 
  filter(.data = d, a %in% .)

but looks like this doesn't work very well:

  a b
1 2 5
Warning message:
In (~.) & (~a %in% .) :
  longer object length is not a multiple of shorter object length

P.S. you don't need to load magrittr explicitly as %>% is already in dplyr

Zafar
  • 1,897
  • 15
  • 33
  • that's strange I thought that whole point of the point was to be able to pipe to whichever argument I wanted – Bruno Oct 14 '17 at 11:58
  • The main rule of the pipe is that it always maps to the first arg, unless you explicitly assign the first arg to something else. – Zafar Oct 15 '17 at 13:43