Unit 04.01: The pipe puts the steps in the order they happen
The pipe does not add capability. It changes reading order from inside-out to top-to-bottom, which is most of what makes analysis code legible.
|> puts the steps in the order they happen
Without a pipe, chained calls nest: the first thing that happens is written innermost, so you read right to left and inside out. With four steps this is genuinely hard to follow.
x |> f() means f(x). Chained, it puts each step on its own line in execution order, so the code reads as the sentence you would say out loud: take the visits, group by ward, total them, sort them.
The pipe passes the left-hand value to the first argument. When you need it somewhere else, _ marks the spot — though it requires the argument to be named.
You will also meet %>% from magrittr in older code. |> is built into R and is the one to write now.
This block computes the same answer nested and piped, then shows the placeholder.
suppressPackageStartupMessages(library(dplyr))
visits <- data.frame(ward = c("North", "South", "East", "North"),
visits = c(412, 388, 502, 455))
# Nested: read it inside-out, right to left.
nested <- head(arrange(summarise(group_by(visits, ward),
total = sum(visits), .groups = "drop"),
desc(total)), 2)
# Piped: read it top to bottom, in the order it happens.
piped <- visits |>
group_by(ward) |>
summarise(total = sum(visits), .groups = "drop") |>
arrange(desc(total)) |>
head(2)
print(piped)
cat("\nSame result:", identical(as.data.frame(nested), as.data.frame(piped)), "\n\n")
# The pipe passes to the FIRST argument. `_` says where to put it instead.
cat("Rows kept when North is excluded:",
nrow(visits |> subset(ward != "North")), "\n")
cat("Placeholder form, visits |> nrow(x = _):", visits |> nrow(x = _), "\n")
Both forms give North 867 and East 502, and the identity check prints TRUE — the pipe is purely a change of notation. The placeholder call visits |> nrow(x = _) returns 4, putting the piped value into a named argument instead of the first position.
The mistake this prevents
The mistake is a pipeline twelve steps long with no intermediate object. It reads well and cannot be debugged, because there is nothing to look at between steps.
Takeaway
Use |> for chains of two to six steps. Break longer chains into named intermediate objects at the points where the data means something new.
