The pipe and dplyr

R · Practical · 15 min

dplyr pipelines are the most common way data is cleaned and summarised in modern R.

The native pipe |> (R 4.1+) passes the left side as the first argument of the call on the right: x |> f(y) is f(x, y). Pipelines read top to bottom instead of inside out. The magrittr pipe %>% predates it and still appears everywhere; for most code they're interchangeable.

dplyr provides one verb per operation, each taking a data frame first and returning a new one:

  • filter(df, cond) keeps rows; arrange(df, desc(x)) sorts.
  • select(df, a, b) picks columns (with helpers like starts_with); rename renames.
  • mutate(df, new = expr) adds or changes columns.
  • summarise(df, n = n(), avg = mean(x)) reduces to one row.
  • group_by(df, g) makes the next summarise or mutate work per group. Use .by = g for a one-off grouping.
  • left_join, inner_join combine tables by key columns.

Inside verbs you refer to columns by bare name (data masking), so filter(df, age > 30) needs no df$. Use .data$col to be explicit, and {{ arg }} when wrapping dplyr in your own functions.

The tidyverse also includes tidyr for reshaping (pivot_longer, pivot_wider) and readr for import; library(tidyverse) loads them together.

Example

library(dplyr, warn.conflicts = FALSE)

mtcars |>
  filter(hp > 100) |>
  mutate(kpl = round(mpg * 0.425, 1)) |>
  group_by(cyl) |>
  summarise(n = n(), avg_kpl = mean(kpl), .groups = "drop") |>
  arrange(desc(avg_kpl)) |>
  print()
#> # A tibble: 3 x 3
#>     cyl     n avg_kpl
#>   <dbl> <int>   <dbl>
#> 1     4     2   11
#> 2     6     7    8.4
#> 3     8    14    6.43

teams <- tibble(cyl = c(4, 8), label = c("small", "big"))
mtcars |> count(cyl) |> left_join(teams, by = "cyl") |> print()
#>   cyl  n label
#> 1   4 11 small
#> 2   6  7  <NA>
#> 3   8 14   big

Remember

  • x |> f(y) means f(x, y)
  • Verbs: filter, select, mutate, summarise, arrange, joins
  • group_by (or .by) makes summaries per group
  • Columns are referenced by bare name inside verbs

Watch out for

  • Forgetting that group_by stays attached to the result, so later mutates run per group unexpectedly.

Check yourself

  1. What is mtcars |> head(3) equivalent to?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: dplyr.tidyverse.org/articles/dplyr.html

Builds on

Unlocks

Nothing builds on this yet.