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.

RRun this once before any exercise
library(dplyr) library(tibble) library(ggplot2)

  

Exercise 1: Mean per group

Difficulty: Beginner.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> summarise(mean_mpg = mean(mpg))

  

Exercise 2: Multiple stats

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> summarise(n = n(), mean = mean(mpg), sd = sd(mpg))

  

Exercise 3: Two-level grouping

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl, gear) |> summarise(mean_mpg = mean(mpg), .groups = "drop")

  

Exercise 4: .groups argument

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl, gear) |> summarise(n = n(), .groups = "drop_last")

  

Exercise 5: ungroup explicitly

Difficulty: Beginner.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> mutate(z = scale(mpg)[,1]) |> ungroup()

  

Exercise 6: filter inside group_by

Difficulty: Intermediate. Per-group threshold.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> filter(mpg > median(mpg)) |> ungroup()

  

Exercise 7: HAVING-style filter

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> filter(n() >= 10) |> summarise(mean_mpg = mean(mpg))

  

Exercise 8: mutate per group

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> mutate(rank_mpg = min_rank(desc(mpg))) |> ungroup()

  

Exercise 9: slice per group

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> slice(1:2) |> ungroup()

  

Exercise 10: slice_max with by

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> tibble::rownames_to_column("car") |> slice_max(mpg, n = 2, by = cyl)

  

Exercise 11: .by argument

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> summarise(mean_mpg = mean(mpg), .by = cyl)

  

Exercise 12: Group-relative proportion

Difficulty: Advanced.

Show solution
RInteractive R
ggplot2::diamonds |> count(cut, clarity) |> group_by(cut) |> mutate(share = n / sum(n)) |> ungroup()

  

Exercise 13: cur_group_id

Difficulty: Advanced.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> mutate(grp_id = cur_group_id()) |> ungroup() |> count(cyl, grp_id)

  

Exercise 14: cur_group()

Difficulty: Advanced.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> summarise(label = paste0("cyl=", cur_group()$cyl), n = n())

  

Exercise 15: Group filter + summarise

Difficulty: Intermediate.

Show solution
RInteractive R
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
RInteractive R
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
RInteractive R
mtcars |> group_by(cyl) |> arrange(desc(mpg), .by_group = TRUE)

  

Exercise 18: Avoid grouped output

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> summarise(mean_mpg = mean(mpg), .groups = "drop")

  

Exercise 19: rolling sum within group

Difficulty: Advanced.

Show solution
RInteractive R
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
RInteractive R
iris |> group_by(Species) |> summarise(across(where(is.numeric), mean))

  

Exercise 21: across with multiple functions

Difficulty: Advanced.

Show solution
RInteractive R
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
RInteractive R
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
RInteractive R
mtcars |> with_groups(cyl, mutate, mean_cyl = mean(mpg))

  

Exercise 24: group_modify

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> group_modify(~ tibble(mean_sl = mean(.x$Sepal.Length)))

  

Exercise 25: group_split

Difficulty: Advanced.

Show solution
RInteractive R
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.