Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

Pipe in R: |> vs %>% With Examples

Pipe in R explained: native |> (R 4.1.0+) vs magrittr %>%, the _ placeholder, and fixes for common pipe errors.

Written and maintained by CASRAI Editorial Board

Last updated

A pipe in R passes the result of one expression into the next call, so a sequence of steps reads left to right instead of inside out. R has two pipes: the native pipe |>, built into base R since version 4.1.0, and the magrittr pipe %>%, which comes from a package. x |> f(y) is parsed as f(x, y), and that single rule is the core of this guide.

Which pipe do you need? Version cheat sheet

The native pipe needs a minimum R version, and two of its features arrived later. Check R.version.string before choosing a pipe for a shared analysis script.

Feature First available in Source
Native pipe |> R 4.1.0 R documentation, ?pipeOp
Placeholder _ (must be a named argument) R 4.2.0 Tidyverse blog, base R vs magrittr pipes
_ as the head of an extraction chain (_$coef[[2]]) R 4.3.0 Tidyverse blog; example in ?pipeOp
magrittr pipe %>% Installed package (magrittr or tidyverse) magrittr site

The R documentation warns that code using the native pipe “will not be parsed as intended (probably with an error) in earlier versions of R.”

What it is used for in research

Research analysis scripts are long chains of small operations: filter the rows, compute a summary, fit a model, draw a figure. Written as nested calls, the order of operations reads from the innermost call outward. A pipe writes the same chain in the order it runs, which makes each step easy to check, add or reorder. The R for Data Science style chapter makes the same point: pipes make it easy to add or rearrange steps.

That readability matters for computational reproducibility, because a collaborator or reviewer who re-runs your script has to follow it line by line. Pipelines typically sit just before a plotting or testing step such as a histogram in R, a scatterplot in R, a box plot in R or a Kruskal-Wallis test in R.

Install or access (official source only)

Native pipe |>

Nothing to install. The native pipe is part of base R from version 4.1.0 onward; the reference page is ?pipeOp in R, or “Forward Pipe Operator” in the base package documentation.

magrittr pipe %>%

The magrittr site gives these install routes:

# easiest: the whole tidyverse
install.packages("tidyverse")

# or just magrittr
install.packages("magrittr")

# development version
pak::pak("tidyverse/magrittr")

Step-by-step: write your first pipeline

  1. Confirm your R version is 4.1.0 or later. Run R.version.string. If it is older, use the magrittr pipe or upgrade R.
  2. Start with a call that has the data as its first argument. The pipe inserts the left-hand side as the first argument of the right-hand call:
    mtcars |> head(2)   # same as head(mtcars, 2)
  3. Chain a second step. Each result becomes the first argument of the next call:
    mtcars |> subset(cyl == 4) |> nrow()   # same as nrow(subset(mtcars, cyl == 4))
  4. Send the value to a different argument with the placeholder. Name the argument and use _ (R 4.2.0 or later):
    mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = _)
  5. Or name the other arguments instead. Naming the arguments before the “one” the pipe fills works without a placeholder:
    mtcars |> subset(cyl == 4) |> lm(formula = mpg ~ disp)
  6. Pull a value out of the result. From R 4.3.0 the placeholder can start an extraction chain:
    mtcars |> subset(cyl == 4) |> lm(formula = mpg ~ disp) |> _$coef[[2]]
  7. Use an anonymous function when the placeholder does not fit. Wrap the function in parentheses and call it:
    mtcars |> subset(cyl == 4) |> (\(d) lm(mpg ~ disp, data = d))()

For the magrittr pipe, x %>% f is equivalent to f(x), and x %>% f(y, z = .) equals f(y, z = x), with . as the placeholder. The magrittr site’s example pipes iris through subset(Sepal.Length > mean(Sepal.Length)) and then the exposition pipe %$% into cor(Sepal.Length, Sepal.Width), which returns 0.3361992.

Output and how to read it

A pipe does not change what the code computes; it only changes how it is written. R’s documentation states that pipe operations are implemented as syntax transformations, so x |> f(y) is parsed as f(x, y). To read a pipeline, replace each |> with “then” and mentally rebuild the nested call:

Pipeline Same as
mtcars |> head() head(mtcars)
mtcars |> head(2) head(mtcars, 2)
mtcars |> subset(cyl == 4) |> nrow() nrow(subset(mtcars, cyl == 4))

Regular R evaluation rules still apply. The documentation shows that in stop() |> (function(...) {})() the call to stop() is never evaluated, because the function on the right does not use its argument. Piped expressions are evaluated only when the right-hand side first uses them.

For script style, R for Data Science recommends a space before |> and, typically, putting it last on a line, and cautions against very long pipes, say longer than 10 to 15 lines:

flights |>
  group_by(tailnum) |>
  summarize(delay = mean(arr_delay, na.rm = TRUE), n = n())

Troubleshooting

Why do I get a parse error on |>?

Your R is probably older than 4.1.0. Code using the native pipe is not parsed as intended in earlier versions. Upgrade R, or use %>% from magrittr.

Why does x |> f fail when x %>% f works?

The right-hand side of the native pipe must be a call. The tidyverse blog notes that %>% lets you drop the parentheses when a function has no other arguments, while |> always requires them. Write x |> f().

Why can’t I pipe into + or if?

Functions in the right-hand call may not be syntactically special, such as + or if.

Why does the _ placeholder not work?

  • It needs R 4.2.0 or later.
  • It must be passed as a named argument, for example x |> f(1, y = _).
  • It can appear only once on the right-hand side.
  • It cannot be sent to several arguments, and it cannot sit inside another function call.
  • As the head of an extraction (_$coef) it needs R 4.3.0 or later.

Why can’t I build a function with . |> f()?

magrittr lets a pipe that starts with . create a function. The tidyverse blog states this is not supported by the base pipe; use an anonymous function such as \(d) f(d) instead.

Alternatives: native pipe vs magrittr pipe

Both pipes do the same basic job. Use this table to translate between them.

Idiom magrittr %>% Native |>
Basic call x %>% f(y) x |> f(y)
Function with no other arguments x %>% f (parentheses optional) x |> f() (parentheses required)
Placeholder symbol . _ (R 4.2.0 or later)
Placeholder rules Can be used several times Named argument only; once only; not inside another function
Create a function by starting with the placeholder . %>% f Not supported
Start an extraction chain mtcars %>% .$cyl _$cyl style heads need R 4.3.0 or later
Where it comes from Package: install.packages("magrittr") or tidyverse Base R 4.1.0 or later

R’s own documentation says the native pipe “is motivated by the pipe introduced in the magrittr package, but is more streamlined.”

FAQ

What is the pipe operator in R?

It is an operator that passes the value on its left into the call on its right. Base R’s version is |> (R 4.1.0 or later), and the magrittr package provides %>%.

What is the difference between |> and %>%?

The native pipe always needs parentheses on the right-hand function, uses a named-argument _ placeholder (R 4.2.0 or later) usable once, and cannot create functions from a leading placeholder. The magrittr pipe allows x %>% f, uses ., and allows several uses of the placeholder.

Do I need to install a package to use |>?

No. It is part of base R from version 4.1.0.

How do I send the piped value to an argument other than the first?

Use the placeholder with a named argument, as in lm(mpg ~ disp, data = _), or name the other arguments so the piped value fills the remaining first position.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Pipe in R: |> vs %>% With Examples

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →