dplyr group_by Exercises in R: 25 Practice Problems
Twenty-five practice problems on dplyr group_by: summarise, mutate, filter, slice, ungroup discipline, .by argument. Hidden solutions.
By Selva Prabhakaran · Published May 11, 2026 · Last updated May 11, 2026
library(dplyr)
library(tibble)
library(ggplot2)
Exercise 1: Mean per group
Difficulty: Beginner.
Show solution
mtcars |> group_by(cyl) |> summarise(mean_mpg = mean(mpg))
Exercise 2: Multiple stats
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |>
summarise(n = n(), mean = mean(mpg), sd = sd(mpg))
Exercise 3: Two-level grouping
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl, gear) |>
summarise(mean_mpg = mean(mpg), .groups = "drop")
Exercise 4: .groups argument
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl, gear) |>
summarise(n = n(), .groups = "drop_last")
Exercise 5: ungroup explicitly
Difficulty: Beginner.
Show solution
mtcars |> group_by(cyl) |> mutate(z = scale(mpg)[,1]) |> ungroup()
Exercise 6: filter inside group_by
Difficulty: Intermediate. Per-group threshold.
Show solution
mtcars |> group_by(cyl) |> filter(mpg > median(mpg)) |> ungroup()
Exercise 7: HAVING-style filter
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |> filter(n() >= 10) |>
summarise(mean_mpg = mean(mpg))
Exercise 8: mutate per group
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |> mutate(rank_mpg = min_rank(desc(mpg))) |> ungroup()
Exercise 9: slice per group
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |> slice(1:2) |> ungroup()
Exercise 10: slice_max with by
Difficulty: Intermediate.
Show solution
mtcars |> tibble::rownames_to_column("car") |>
slice_max(mpg, n = 2, by = cyl)
Exercise 11: .by argument
Difficulty: Intermediate.
Show solution
mtcars |> summarise(mean_mpg = mean(mpg), .by = cyl)
Exercise 12: Group-relative proportion
Difficulty: Advanced.
Show solution
ggplot2::diamonds |>
count(cut, clarity) |>
group_by(cut) |> mutate(share = n / sum(n)) |> ungroup()
Exercise 13: cur_group_id
Difficulty: Advanced.
Show solution
mtcars |> group_by(cyl) |>
mutate(grp_id = cur_group_id()) |>
ungroup() |>
count(cyl, grp_id)
Exercise 14: cur_group()
Difficulty: Advanced.
Show solution
mtcars |> group_by(cyl) |>
summarise(label = paste0("cyl=", cur_group()$cyl), n = n())
Exercise 15: Group filter + summarise
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |>
filter(mpg > 20) |>
summarise(n = n(), mean_mpg = mean(mpg), .groups = "drop")
Exercise 16: First/last per group
Difficulty: Intermediate.
Show solution
df <- tibble(g = c("a","a","b","b"), v = c(1,2,3,4))
df |> group_by(g) |> summarise(first_v = first(v), last_v = last(v))
Exercise 17: arrange within group_by
Difficulty: Intermediate. arrange respects groups when .by_group=TRUE.
Show solution
mtcars |> group_by(cyl) |> arrange(desc(mpg), .by_group = TRUE)
Exercise 18: Avoid grouped output
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |>
summarise(mean_mpg = mean(mpg), .groups = "drop")
Exercise 19: rolling sum within group
Difficulty: Advanced.
Show solution
tibble(g = c("a","a","a","b","b"), v = c(2, 4, 6, 3, 5)) |>
group_by(g) |> mutate(cs = cumsum(v)) |> ungroup()
Exercise 20: across in summarise per group
Difficulty: Advanced.
Show solution
iris |> group_by(Species) |>
summarise(across(where(is.numeric), mean))
Exercise 21: across with multiple functions
Difficulty: Advanced.
Show solution
iris |> group_by(Species) |>
summarise(across(where(is.numeric),
list(mean = mean, sd = sd),
.names = "{.col}_{.fn}"))
Exercise 22: reframe (multiple rows)
Difficulty: Advanced.
Show solution
mtcars |> group_by(cyl) |>
reframe(q = c("p25","p50","p75"),
mpg = quantile(mpg, c(0.25, 0.5, 0.75)))
Exercise 23: with_groups()
Difficulty: Advanced.
Show solution
mtcars |> with_groups(cyl, mutate, mean_cyl = mean(mpg))
Exercise 24: group_modify
Difficulty: Advanced.
Show solution
iris |> group_by(Species) |>
group_modify(~ tibble(mean_sl = mean(.x$Sepal.Length)))
Exercise 25: group_split
Difficulty: Advanced.
Show solution
iris |> group_by(Species) |> group_split() |> length()
What to do next
- dplyr-Exercises (shipped), broader practice.
- dplyr-Joins-Exercises, dplyr-Window-Functions-Exercises (shipped), focused drills.