Pipe polishing

This commit is contained in:
Hadley Wickham 2022-02-23 13:33:21 -06:00
parent da0fbd50d5
commit 6641284e4c
1 changed files with 28 additions and 27 deletions

View File

@ -5,11 +5,23 @@ status("restructuring")
```
The pipe, `|>`, is a powerful tool for clearly expressing a sequence of operations that transform an object.
We briefly introduced them in the previous chapter but before going too much farther I wanted to give a little more motivation and discuss another pipe that you're likely to see in the wild.
We briefly introduced pipes in the previous chapter but before going too much farther I wanted to give a few more details and discuss, `%>%`, an predecessor to `|>`.
To add the pipe to your code, we recommend using the build-in keyboard shortcut Ctrl/Cmd + Shift + M.
You'll need to make one change to your RStudio options to use `|>` instead of `%>%` as shown in Figure \@ref(fig:pipe-options); more `%>%` that next.
```{r pipe-options, out.width = NULL, echo = FALSE}
#| fig.cap: >
#| To insert `|>`, make sure the "Use native pipe" option is checked.
#| fig.alt: >
#| Screenshot showing the "Use native pipe operator" option which can
#| be found on the "Editing" panel of the "Code" options.
knitr::include_graphics("screenshots/rstudio-pipe-options.png")
```
## Why use a pipe?
Because each individual dplyr function is quite simple, solving complex problems typically require multiple verbs together.
Each individual dplyr function is quite simple so solving complex problems typically require multiple verbs together.
For example, the last chapter finished with a moderately complex pipe:
```{r, eval = FALSE}
@ -22,7 +34,7 @@ flights |>
)
```
Even though this pipe has four steps, because the verbs come at the start of each line, it's quite easy to skim: we start with flights, then filter, then group, then summarize.
Even though this pipe has four steps, it's quite easy to skim because the verbs come at the start of each line: we start with the flights data, then filter, then group, then summarize.
What would happen if we didn't have the pipe?
We could nest each function call inside the previous call:
@ -55,22 +67,10 @@ flights3 <- summarise(flight2,
While both of these forms have their place and time, the pipe generally produces code that is easier to read and easier to write.
To add the pipe to your code, we recommend using the build-in keyboard shortcut Ctrl/Cmd + Shift + M.
You'll also need to make one change to your RStudio options to use the base pipe instead of the magrittr pipe as shown in Figure \@ref(fig:pipe-options); more on that next.
```{r pipe-options, out.width = NULL, echo = FALSE}
#| fig.cap: >
#| To insert `|>`, make sure the "Use native pipe" option is checked.
#| fig.alt: >
#| Screenshot showing the "Use native pipe operator" option which can
#| be found on the "Editing" panel of the "Code" options.
knitr::include_graphics("screenshots/rstudio-pipe-options.png")
```
## magrittr and the `%>%` pipe
If you've been using the tidyverse for a while, you might have been be more familiar with the `%>%` pipe provided by the **magrittr** package by Stefan Milton Bache.
The magrittr package is included in the code the tidyverse, so you can use `%>%` whenever you use the tidyverse:
If you've been using the tidyverse for a while, you might be more familiar with the `%>%` pipe provided by the **magrittr** package.
The magrittr package is included in the code the tidyverse, so you can use `%>%` whenever you load the tidyverse:
```{r, message = FALSE}
library(tidyverse)
@ -83,7 +83,8 @@ mtcars %>%
For simple cases `|>` and `%>%` behave identically.
So why do we recommend the base pipe?
Firstly, because it's part of base R, it's always available for you to use, even when you're not using the tidyverse.
Secondly, the `|>` is quite a bit simpler than `%>%`: in the 7 years between the invention of `%>%` in 2014 and the inclusion of `|>` in R 4.1.0 in 2021, we better learned what the core strength of the pipe was, allowing the base implementation to jettison infrequently used and less important features.
Secondly, `|>` is quite a bit simpler than `%>%`: in the time between the invention of `%>%` in 2014 and the inclusion of `|>` in R 4.1.0 in 2021, we gained a better understanding of the pipe.
This allowed the base implementation to jettison infrequently used and less important features.
## Base pipe vs magrittr pipe
@ -91,14 +92,16 @@ While `|>` and `%>%` behave identically for simple cases there are a few importa
These are most likely to affect you if you're a long-term `%>%` user who has taken advantage of some of the more advanced features.
But they're good to know about even if you've never used `%>%`, because you're likely to encounter some of them when reading wild-caught code.
- The pipe requires that object on the left hand side be passed to the first argument of the function on the right-hand side.
`%>%` allows you change the placement using `.` as a placeholder.
- By default, the pipe passes the object on its left hand side to the first argument of the function on the right-hand side.
`%>%` allows you change the placement a `.` placeholder.
For example, `x %>% f(1)` is equivalent to `f(x, 1)` but `x %>% f(1, .)` is equivalent to `f(1, x)`.
R 4.2.0 will bring a `_` as a placeholder, but it has to be named, so you could write `x |> f(1, y = _)`.
The base placeholder is deliberately simple; you can't pass it to multiple arguments, and it doesn't have the special behavior that `%>%` does when used with `{}`.
R 4.2.0 will bring a `_` as a placeholder to the base pipe, with one additional restriction: the argument has to be named.
For example, `x |> f(1, y = _)` is equivalent to `f(1, y = x)`.
You can also use both `.` and `_` on the left-hand side of operators like `$`, `[[`, `[` (which you'll learn about in Chapter \@ref(vectors)):
- The `|>` placeholder is deliberately simple and can't replicate many features of the `%>%` placeholder: you can't pass it to multiple arguments, and it doesn't have any special behavior when the placeholder is used inside another function (i.e. `df %>% split(.$var)` is equivalent to `split(df, df$var)`.
- You can also use both `.` and `_` on the left-hand side of operators like `$`, `[[`, `[` (which you'll learn about in Chapter \@ref(vectors)):
``` r
mtcars %>% .$cyl
@ -111,8 +114,6 @@ But they're good to know about even if you've never used `%>%`, because you're l
mtcars |> pull(cyl)
```
- When calling a function with no argument, `%>%` allowed you to drop the drop the parentheses, and write (e.g.) `x %>% ungroup`.
`|>` always requires the parentheses.
- `%>%` allowed you to drop the parentheses when calling a function with no other arguments; `|>` always requires the parentheses.
- Starting a pipe with `.`, like `. %>% group_by(x) %>% summarise(x)` would create a function rather than immediately performing the pipe.
This is an error with the base pipe.
- `%>%` allowed you to starting a pipe with `.` to create a function rather than immediately executing the pipe; this is not supported by the base pipe.