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.
By Selva Prabhakaran · Published May 11, 2026 · Last updated May 11, 2026
library(tidyr)
library(dplyr)
library(purrr)
library(tibble)
library(broom)
Exercise 1: nest by group
Difficulty: Intermediate.
Show solution
iris |> group_by(Species) |> nest()
Exercise 2: nest specific columns
Difficulty: Intermediate.
Show solution
iris |> nest(sepal = starts_with("Sepal"))
Exercise 3: unnest
Difficulty: Intermediate.
Show solution
nested <- iris |> group_by(Species) |> nest()
nested |> unnest(data)
Exercise 4: unnest_longer (vectors)
Difficulty: Advanced.
Show solution
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
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
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
iris |> pack(sepal = starts_with("Sepal"))
Exercise 8: unpack
Difficulty: Advanced.
Show solution
packed <- iris |> pack(sepal = starts_with("Sepal"))
packed |> unpack(sepal)
Exercise 9: chop
Difficulty: Advanced.
Show solution
tibble(id = c(1,1,2,2), v = 1:4) |> chop(v)
Exercise 10: unchop
Difficulty: Advanced.
Show solution
tibble(id = 1:2, v = list(1:2, 3:4)) |> unchop(v)
Exercise 11: nest into list-column from groups
Difficulty: Intermediate.
Show solution
mtcars |> group_by(cyl) |> nest()
Exercise 12: Many models per group
Difficulty: Advanced.
Show solution
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
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
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
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
iris |>
group_by(Species) |>
summarise(stats = list(summary(Sepal.Length)))
Exercise 17: unnest_longer with names
Difficulty: Advanced.
Show solution
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
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
mtcars |> group_by(cyl, gear) |> nest()
Exercise 20: List-column from a custom function
Difficulty: Advanced.
Show solution
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
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
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
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
iris |>
group_by(Species) |>
nest() |>
mutate(_ = walk2(data, Species, ~ message(.y, ": ", nrow(.x), " rows")))
Exercise 25: Round-trip nest -> unnest
Difficulty: Intermediate.
Show solution
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.