tidyr Nest and Unnest Exercises in R: 25 Practice Problems

Twenty-five practice problems on nest, unnest, hoist, pack, unpack, and the many-models pattern. Hidden solutions.

RRun this once before any exercise
library(tidyr) library(dplyr) library(purrr) library(tibble) library(broom)

  

Exercise 1: nest by group

Difficulty: Intermediate.

Show solution
RInteractive R
iris |> group_by(Species) |> nest()

  

Exercise 2: nest specific columns

Difficulty: Intermediate.

Show solution
RInteractive R
iris |> nest(sepal = starts_with("Sepal"))

  

Exercise 3: unnest

Difficulty: Intermediate.

Show solution
RInteractive R
nested <- iris |> group_by(Species) |> nest() nested |> unnest(data)

  

Exercise 4: unnest_longer (vectors)

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:2, vals = list(c(10,20), c(30,40,50))) |> unnest_longer(vals)

  

Exercise 5: unnest_wider (named lists)

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:2, payload = list(list(a=1,b=2), list(a=10,b=20))) |> unnest_wider(payload)

  

Exercise 6: hoist specific fields

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:2, payload = list(list(a=1,b=2,c=3), list(a=10,b=20,c=30))) |> hoist(payload, val_a = "a", val_c = "c")

  

Exercise 7: pack

Difficulty: Advanced.

Show solution
RInteractive R
iris |> pack(sepal = starts_with("Sepal"))

  

Exercise 8: unpack

Difficulty: Advanced.

Show solution
RInteractive R
packed <- iris |> pack(sepal = starts_with("Sepal")) packed |> unpack(sepal)

  

Exercise 9: chop

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = c(1,1,2,2), v = 1:4) |> chop(v)

  

Exercise 10: unchop

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:2, v = list(1:2, 3:4)) |> unchop(v)

  

Exercise 11: nest into list-column from groups

Difficulty: Intermediate.

Show solution
RInteractive R
mtcars |> group_by(cyl) |> nest()

  

Exercise 12: Many models per group

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> nest() |> mutate(model = map(data, ~ lm(Sepal.Length ~ Petal.Length, data = .x)))

  

Exercise 13: Tidy results from per-group models

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> nest() |> mutate(model = map(data, ~ lm(Sepal.Length ~ Petal.Length, data = .x)), tidy = map(model, broom::tidy)) |> unnest(tidy)

  

Exercise 14: Glance per group

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> nest() |> mutate(model = map(data, ~ lm(Sepal.Length ~ Petal.Length, data = .x)), glance = map(model, broom::glance)) |> unnest(glance) |> select(Species, r.squared, p.value)

  

Exercise 15: Predict back into the data

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> nest() |> mutate(model = map(data, ~ lm(Sepal.Length ~ Petal.Length, data = .x)), pred = map2(model, data, ~ predict(.x, .y))) |> unnest(c(data, pred))

  

Exercise 16: nest then summarise list-col

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> summarise(stats = list(summary(Sepal.Length)))

  

Exercise 17: unnest_longer with names

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:2, vals = list(c(a=1, b=2), c(a=10, b=20))) |> unnest_longer(vals)

  

Exercise 18: hoist with deep paths

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1, json = list(list(meta = list(version = "1.2"), data = 5))) |> hoist(json, version = c("meta","version"), data = "data")

  

Exercise 19: nest by multiple vars

Difficulty: Advanced.

Show solution
RInteractive R
mtcars |> group_by(cyl, gear) |> nest()

  

Exercise 20: List-column from a custom function

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> summarise(quartiles = list(quantile(Sepal.Length, c(0.25, 0.5, 0.75))))

  

Exercise 21: unnest with names_repair

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:2, v1 = list(tibble(x = 1)), v2 = list(tibble(x = 2))) |> unnest(c(v1, v2), names_repair = "unique")

  

Exercise 22: Filter list elements then unnest

Difficulty: Advanced.

Show solution
RInteractive R
tibble(id = 1:3, v = list(1:3, 1, 1:5)) |> mutate(v = map(v, ~ .x[.x > 1])) |> unnest_longer(v)

  

Exercise 23: nest_join

Difficulty: Advanced.

Show solution
RInteractive R
parents <- tibble(id = 1:2) children <- tibble(parent_id = c(1,1,2), value = c("a","b","c")) parents |> nest_join(children, by = c("id" = "parent_id"))

  

Exercise 24: Walk per nested group

Difficulty: Advanced.

Show solution
RInteractive R
iris |> group_by(Species) |> nest() |> mutate(_ = walk2(data, Species, ~ message(.y, ": ", nrow(.x), " rows")))

  

Exercise 25: Round-trip nest -> unnest

Difficulty: Intermediate.

Show solution
RInteractive R
n <- iris |> group_by(Species) |> nest() back <- n |> unnest(data) identical(arrange(iris, Species), arrange(back, Species))

  

What to do next

  • tidyr-Exercises (shipped), broader tidyr practice.
  • purrr-Exercises (shipped), list-col iteration drills.