Lesson 4 of 4

Nesting & Rectangling

In Lesson 3 you cleaned messy columns and keys. This is the last reshape in the course, and the most surprising one: a single cell can hold not a word or a number, but an entire table.

Maya, who runs a small bakery, has grown to three branches: Riverside, Hilltop and Station. She keeps one tidy row per branch per month, and now she wants one thing per branch: first an average, then a sales trend (is this branch growing or shrinking?). Doing that branch by branch, by hand, is exactly the tedium this lesson removes.

By the end you will be able to:

  • Build a list-column (a column whose cells are whole tables) with nest()
  • Run a summary, and even a whole model, over every group at once with map(), and flatten the result with unnest()
  • Rectangle nested, JSON-like data into tidy rows and columns with unnest_wider(), unnest_longer() and hoist()

Prerequisites: you can run R, and you know a tibble, the pipe %>% and the dplyr verbs. You met nest() briefly in Lesson 2; here we build on it properly. Press Run to see where we are heading.

The new idea

A cell can hold a table

Every table you have made so far holds simple values: a cell is one number, one word, one date. A list-column breaks that rule. Each of its cells holds a whole R object, and the object we care about here is a smaller tibble. Picture a column called data where the Riverside cell is Riverside's little month-and-units table, the Hilltop cell is Hilltop's, and so on.

Why would you want that? Because once each branch's rows are bundled into a single cell, you can do one operation per branch (compute a trend, fit a model, write one file) while still treating the whole thing as one tidy table of three rows.

Each lesson runs in a fresh R session, so we build Maya's three-branch sales right here as a tidy long table. month is stored as a number (month 1 is January) so we can model the trend later:

RInteractive R
library(dplyr) # the pipe and the verbs library(tidyr) # nest(), unnest(), unnest_wider(), unnest_longer(), hoist() library(purrr) # map(), map_dbl() library(tibble) # tribble() sales <- tribble( ~branch, ~month, ~units, "Riverside", 1, 40, "Riverside", 2, 44, "Riverside", 3, 49, "Hilltop", 1, 33, "Hilltop", 2, 30, "Hilltop", 3, 28, "Station", 1, 52, "Station", 2, 55, "Station", 3, 60 ) sales #> # A tibble: 9 x 3 #> branch month units #> <chr> <dbl> <dbl> #> 1 Riverside 1 40 #> 2 Riverside 2 44 #> 3 Riverside 3 49 #> # ... 6 more rows

  

Nine rows, three branches. The next move folds each branch's three rows into a single cell.