tidyr pack() in R: Combine Columns Into a Single df-Column
The pack() function in tidyr combines multiple columns into a single COLUMN OF TIBBLES (a "df-column"). It is the wide-to-grouped version of nesting, useful for organizing related columns.
df |> pack(metrics = c(mpg, hp, wt)) # 3 cols -> 1 df-col 'metrics' df |> pack(coords = c(lon, lat), score = c(s1, s2)) df |> unpack(metrics) # opposite: spread back df |> nest(.by = group) # different: nest by row groups
Need explanation? Read on for examples and pitfalls.
What pack() does in one sentence
pack(data, ...) combines multiple columns into a SINGLE column where each cell is a one-row tibble. Useful for organizing related metrics together while preserving access to individual fields.
Syntax
pack(data, ..., .names_sep = NULL). ... is new_col = c(c1, c2, ...).
pack() is rarely the first tool you reach for. It is mostly used for organizing wide data with semantically grouped columns (e.g., "address fields", "performance metrics") into a hierarchical structure.Five common patterns
1. Group related columns
2. Multiple groups
3. Reverse with unpack
4. Use names_sep for prefix
5. Access packed elements with $
pack() is the OPPOSITE of unpack(), just as nest is the opposite of unnest. They form a pair: pack creates df-columns; unpack flattens them. Same names, different shapes.pack() vs nest() vs unite()
| Function | Combines | Output |
|---|---|---|
pack() |
Columns into one df-column | New df-column |
nest() |
Rows into one list-column per group | New list-column, fewer rows |
unite() |
Columns into one string column | One string column |
When to use which:
- pack for organizing semantic groups of columns.
- nest for collapsing rows per group.
- unite for stringy column concatenation.
A practical workflow
Use pack to organize WIDE data with implicit groupings into hierarchical structure.
Each top-level column is a logical group; access fields via $temperature$temp_min.
Common pitfalls
Pitfall 1: rare in everyday work. pack and unpack are niche. Most analysis pipelines never need them.
Pitfall 2: confusing pack with nest. pack groups COLUMNS together (wide-to-hierarchical). nest groups ROWS together (long-to-list). Different orientations.
pack() makes downstream code more complex because columns become df-columns accessed via $ chains. Only pack when the hierarchical structure adds clarity.Try it yourself
Try it: Pack 3 dimension columns of iris into one "size" df-column. Save to ex_packed.
Click to reveal solution
Explanation: pack groups the 4 dimension columns under "size". The result is a 2-column tibble where size is a 4-column df-column.
Related tidyr functions
After mastering pack, look at:
unpack(): opposite (spread df-column to columns)nest(): per-group row collapsingunite(): combine to string columnpivot_wider()/pivot_longer(): structural reshape
FAQ
What does pack do in tidyr?
pack(data, name = c(cols)) combines multiple columns into a single column where each cell is a 1-row tibble. Used for organizing related columns hierarchically.
What is the difference between pack and nest?
pack groups COLUMNS together (wide-to-hierarchical, same row count). nest groups ROWS together (long-to-list, fewer rows).
How do I access a packed column's fields?
Use $ chains: df$packed_col$inner_col. Or unpack(packed_col) to flatten.
Is pack commonly used?
Rarely. Most workflows don't need it. Reserve for explicitly hierarchical wide data.
What is the inverse of pack?
unpack(). Together they round-trip: pack(...) |> unpack(...) returns the original.