tidyr separate_longer_delim() in R: Split Column Into Rows
The separate_longer_delim() function in tidyr 1.3 splits a column's values by a delimiter and creates ONE NEW ROW per part. It is the tidy-data unstacking idiom: comma-separated lists become individual rows.
df |> separate_longer_delim(tags, delim = ",") # one row per tag df |> separate_longer_delim(items, delim = "; ") df |> separate_longer_delim(c(col1, col2), delim = ",") # multiple cols tidyr::separate_rows(df, tags, sep = ",") # superseded predecessor df |> separate_wider_delim(...) # different: into columns
Need explanation? Read on for examples and pitfalls.
What separate_longer_delim() does in one sentence
separate_longer_delim(data, cols, delim) splits each value of cols by delim and creates ONE NEW ROW per resulting part. Other columns' values are duplicated for each new row.
This unstacks delimiter-separated lists into the standard tidy "one observation per row" format.
Syntax
separate_longer_delim(data, cols, delim). delim is a literal string (not regex).
Five common patterns
1. Comma-separated tags
2. Multi-character delimiter
3. Multiple columns at once
4. Trim whitespace post-split
5. Empty / NA handling
separate_longer_delim() is the modern replacement for separate_rows().* Same semantics; cleaner name and consistency with separate_wider_. The _longer_ and _wider_ naming aligns with pivot_longer / pivot_wider conventions.separate_longer_delim() vs separate_rows() vs unnest()
| Function | Status | Input | Best for |
|---|---|---|---|
separate_longer_delim() |
Recommended | String column | Modern delimiter-to-rows |
tidyr::separate_rows() |
Superseded | String column | Same; older API |
tidyr::unnest() |
Recommended | List column | Already-list-shaped data |
unnest_longer() |
Recommended | List column | Single column to rows |
When to use which:
- separate_longer_delim for delimiter-separated strings.
- unnest for list columns (e.g., from JSON).
- Avoid separate_rows in new code.
A practical workflow
Use separate_longer_delim for "tags" or "tags-like" data normalization.
Tag frequency analysis from comma-separated tag strings. Common pre-processing for text data.
Common pitfalls
Pitfall 1: forgetting to trim whitespace. "a, b, c" splits to "a", " b", " c". Use mutate(col = trimws(col)) after.
Pitfall 2: confusing wider vs longer. wider splits into COLUMNS. longer splits into ROWS. Pick by what you want.
separate_longer_delim() requires tidyr 1.3+. Earlier versions only have separate_rows(). Check packageVersion("tidyr") if confused.Try it yourself
Try it: Split a genres column of comma-separated movie genres into one row per genre. Save to ex_long.
Click to reveal solution
Explanation: Each comma-separated genre becomes its own row; movie name is repeated.
Related tidyr functions
After mastering separate_longer_delim, look at:
separate_longer_position(): split into rows by character positionseparate_wider_delim(): split into columnsseparate_rows(): superseded predecessorunnest_longer(): list column to rowstidyr::nest()/unnest(): list-column workflows
For combining rows back into delimiter-separated strings, use summarise(col = paste(col, collapse = ",")) after grouping.
FAQ
What does separate_longer_delim do in tidyr?
Splits a column's values by a delimiter and creates one row per resulting part. Other columns are duplicated to match.
What is the difference between separate_longer_delim and separate_rows?
separate_rows is superseded by separate_longer_delim (and separate_longer_position). Same semantics, modern naming.
What is the difference between separate_longer_delim and separate_wider_delim?
longer creates new ROWS (one per part). wider creates new COLUMNS (one per part). Same input; different output shape.
How do I trim whitespace after split?
mutate(col = trimws(col)) after the split. Or strip whitespace with strsplit + trimws before separate.
What happens with NAs?
NA values produce one row with NA. Empty strings produce one row with "". Filter after if you don't want them.