3

While I have a (somewhat convoluted) work-around, I'm trying to figure out why subsetting with square brackets ([]) does not work the same when piping results from dplyr functions.

For a really simple demonstration. The first two work:

library(dplyr)

my_data <- mtcars %>% 
  filter(qsec == 16.46)
my_data[,"gear"]
#[1] 4

filter(mtcars, qsec == 16.46)[,"gear"]
#[1] 4

However, the following fails:

mtcars %>% filter(qsec == 16.46)[,"gear"]

#Error in filter(qsec == 16.46) : object 'qsec' not found

I can't seem to find anything that will allow this notation to work. I can get around it by doing some things like:

mtcars %>% 
  filter(qsec == 16.46) %>% 
  select(gear) %>% 
  as.numeric()
#[1] 4

mtcars %>% 
  filter(qsec == 16.46) %>% 
  subset(subset = TRUE, select = "gear") %>% 
  as.numeric()
#[1] 4

But that's adding minimum of two piped functions (depending on what you are needing to subset), and it seems like the square bracket notation should work, but does not, at least, not in the way I expect.

Any insight on why filter(mtcars, qsec == 16.46)[,"gear"] works, but mtcars %>% filter(qsec == 16.46)[,"gear"] does not?

michdn
  • 73
  • 1
  • 1
  • 7
  • There is `pull` `mtcars %>% filter(qsec == 16.46) %>% pull(qsec)` or `mtcars %>% filter(qsec == 16.46) %>% .[, "qsec"] [1] 16.46` – akrun Jul 19 '19 at 21:21
  • 1
    Or enclose it inside the `()` `(mtcars %>% filter(qsec == 16.46))[, "qsec"]# [1] 16.46` otherwise, it would look for operator precedence (Check the `?Syntax`) – akrun Jul 19 '19 at 21:23
  • This works: `mtcars %>% { filter(., qsec == 16.46)[, "gear"] }` – G. Grothendieck Jul 19 '19 at 21:26
  • 2
    In a dplyr pipe you could use:mtcars %>% filter(qsec == 16.46) %>% .[,"gear"] – TimTeaFan Jul 19 '19 at 21:27
  • Awesome, thank you all! I knew there had to be some things I was overlooking. I especially like the `%>% .[,"gear"]` option. I have some code to go clean up now. – michdn Jul 19 '19 at 21:47

1 Answers1

2

To answer your question: The magritte pipe puts the left-hand-side (lhs) as first argument in the function of the right-hand-side. You can suppress this behavior by using curly braces as shown by G. Grothendieck in the comments. If you don’t the input of the lhs is put in the subset function [], which causes said error.

You can play around using the paste function. The example below is from the magrittr documentation.

sample(1:5) %>% paste0(LETTERS[.])
> [1] "4D" "2B" "5E" "3C" "1A"

sample(1:5) %>% {paste0(LETTERS[.])}
> [1] "D" "B" "E" "A" "C"
TimTeaFan
  • 17,549
  • 4
  • 18
  • 39