tidyr uncount() in R: Expand Frequency Counts Into Rows
The uncount() function in tidyr expands a data frame where one column holds frequency counts into one row per count unit. It is the opposite of dplyr::count().
df |> uncount(n) # repeat each row n times df |> uncount(n, .remove = FALSE) # keep the n column df |> uncount(n, .id = "row_id") # add row index dplyr::count(df, ...) # opposite operation
Need explanation? Read on for examples and pitfalls.
What uncount() does in one sentence
uncount(data, weights, .remove = TRUE, .id = NULL) repeats each row of data weights times, expanding a frequency-count table into individual rows. It reverses dplyr's count().
Syntax
uncount(data, weights, .remove = TRUE, .id = NULL). weights is the count column.
Five common patterns
1. Standard expansion
2. Keep original count
3. Add row index
4. After dplyr count
5. Use to simulate / replicate
uncount is dplyr count's INVERSE. count rolls rows into a frequency table; uncount expands a frequency table back into rows. Useful when downstream code needs row-per-event format.uncount() vs base rep() vs count()
| Function | Direction | Input |
|---|---|---|
uncount(data, n) |
Expand | Frequency table |
dplyr::count(data, g) |
Collapse | Row-per-event |
base::rep(x, times) |
Expand | Vector |
When to use which:
- uncount for data frame frequency expansion.
- count for row aggregation.
- rep for vector / non-data frame.
A practical workflow
Use uncount when bridging summary data to row-level analysis.
Each summary row expands to N rows; row_number adds a unique id.
Common pitfalls
Pitfall 1: confusing direction. uncount EXPANDS; count COLLAPSES. They are opposites.
Pitfall 2: zero or negative counts. uncount with n = 0 produces no rows for that input. Negative weights error.
uncount can produce HUGE output. A row with n = 1,000,000 expands to a million rows. Check sizes first.Try it yourself
Try it: Expand a frequency table of cars by gear count. Save to ex_expanded.
Click to reveal solution
Explanation: count produced (gear, n) rows; uncount(n) expands to 32 rows total.
Related tidyr / dplyr functions
After mastering uncount, look at:
dplyr::count(): opposite (collapse to frequency)dplyr::add_count(): count without collapsingbase::rep(): vector replicationtidyr::complete(): fill missing combinations
FAQ
What does uncount do in tidyr?
uncount(data, n) repeats each row n times, expanding a frequency-count table into individual rows. Opposite of dplyr's count.
What is the difference between uncount and count?
count COLLAPSES rows into a frequency table. uncount EXPANDS a frequency table back into rows. Opposite operations.
How do I keep the original count column?
Pass .remove = FALSE. Each row is still repeated; the count column survives.
How do I add an id within each expansion?
Pass .id = "instance". Adds a column with 1, 2, 3, ... per repetition.
What if a count is 0?
That row contributes 0 rows to the output. Negative weights error.