The Pipe Operator in R: %>% vs |> — Master the Most Important Concept
The pipe operator takes the output of one function and feeds it as the first argument to the next function. It turns deeply nested function calls into readable, left-to-right chains. If you learn one concept in modern R, make it this one.
Before pipes, R code looked like this: round(mean(subset(mtcars, cyl == 6)$mpg), 2). You have to read it inside-out. With pipes, the same code reads top-to-bottom, like a recipe. R has two pipes: %>% from the magrittr package and |> built into R 4.1+. This tutorial covers both.
The Problem Pipes Solve
Without pipes, you have three options for multi-step operations — and all of them have problems:
The pipe |> says: "Take what's on the left and pass it as the first argument to what's on the right."
The magrittr Pipe: %>%
The %>% pipe was introduced by the magrittr package in 2014 and popularized by the tidyverse. It's available whenever you load dplyr, tidyr, or any tidyverse package.
magrittr's Extra Pipes
The magrittr package provides three additional pipe variants:
The Native Pipe: |>
R 4.1 (2021) introduced the native pipe |>. It's built into the language — no packages needed.
%>% vs |>: Key Differences
| Feature | %>% (magrittr) |
` | >` (native) |
|---|---|---|---|
| Available since | 2014 (package) | R 4.1 (2021) | |
| Requires package | Yes (magrittr/dplyr) | No | |
| Placeholder | . (anywhere, multiple times) |
_ (named args only, once) |
|
| Performance | Slight overhead | Zero overhead | |
| Debugging | Stack traces show %>% internals |
Cleaner stack traces | |
| Lambda syntax | . %>% { ... } |
\(x) ... |
|
| Extra pipes (%T>%, %<>%) | Yes | No |
When to Use Pipes (and When Not To)
Pipes work best for linear sequences of transformations:
Pipes are a poor fit when:
Rules of Thumb
- Use pipes for 2-10 step linear transformations
- Save to a variable when you need intermediate results more than once
- Don't pipe into a function call with side effects (plotting, writing files) unless you use
%T>% - Break long pipes (10+ steps) into named stages
Keyboard Shortcuts
In RStudio, type the pipe instantly:
| Pipe | Shortcut (Windows/Linux) | Shortcut (Mac) | |
|---|---|---|---|
%>% |
Ctrl + Shift + M | Cmd + Shift + M | |
| ` | >` | Ctrl + Shift + M (if configured) | Cmd + Shift + M |
To switch RStudio's default pipe: Tools > Global Options > Code > Use native pipe operator
Practice Exercises
Exercise 1: Rewrite this nested code using pipes. Use whichever pipe you prefer.
Click to reveal solution
```rExercise 2: Use a pipe chain with dplyr to find the top 3 heaviest cars (by wt) that have more than 100 horsepower. Show only mpg, hp, and wt.
Click to reveal solution
```rExercise 3: The lm() function takes data as its second argument, not its first. Use a pipe to pass mtcars into lm(mpg ~ wt, data = ...) using either |> with _ or %>% with ..
Click to reveal solution
```rFAQ
Q: Which pipe should I use in 2026? Use the native pipe |> as your default. It's faster, needs no packages, and produces cleaner error messages. Switch to %>% only when you need the dot placeholder in unusual positions or the tee pipe %T>%.
**Q: Can I mix %>% and |> in the same chain?** Technically yes, but don't. Pick one per chain for readability. It's fine to use different pipes in different parts of a script.
Q: Why does my pipe chain give a different result than the nested version? The most common cause: you forgot that the pipe passes to the first argument. If the function you're piping into doesn't take data as its first argument, use a placeholder (_ or .).
What's Next?
With pipes in your toolkit, you're ready to start transforming data. The next tutorial covers dplyr filter() and select() — the two functions you'll use most often to subset rows and columns.