Programming

Repeat each row of dataframe the number of times specified in a column

25 September 2026 · 6 min read

Repeat each row of dataframe the number of times specified in a column

Data manipulation is a cornerstone of effective data analysis, and often, the need arises to transform your datasets in specific ways to prepare them for modeling or reporting. One common yet sometimes tricky task is to repeat each row of a data.frame the number of times specified in a column. This operation, often called row replication or data expansion, is vital when you have aggregated data and need to disaggregate it back into individual observations, or when simulating scenarios where each record represents multiple occurrences. For instance, if you have a dataset where one column indicates the count of an event, you might need to expand that single row into multiple rows, one for each reported occurrence. This article will guide you through various robust methods in R, from foundational base R techniques to elegant tidyverse solutions, ensuring you can tackle this data preparation challenge efficiently and accurately.

Why & When You Need to Replicate Rows

The necessity to replicate rows based on a column’s value typically emerges from specific data structures or analytical requirements. Consider a scenario in manufacturing where a single record represents a batch of items, and a column specifies the quantity produced in that batch. For individual item tracking, you’d need to expand that single batch row into multiple rows, one for each item. Similarly, in survey data, if a response represents multiple individuals (e.g., “household size”), expanding these rows allows for individual-level analysis.

This data expansion is crucial for many statistical models that assume each row is an independent observation. For example, when fitting a regression model, if your data is aggregated, you might incorrectly weigh certain observations. By expanding the data, each individual instance gets its proper representation. It’s also invaluable for creating visual representations where each point represents a single occurrence rather than an aggregated count, making patterns clearer and more interpretable. According to a 2023 survey by KDnuggets on data science skills, data cleaning and preparation continue to be among the most time-consuming tasks for data professionals, highlighting the importance of mastering such techniques.

Understanding the context for this operation helps in choosing the most appropriate method. Whether you’re dealing with inventory management, epidemiological data, or market research, the ability to accurately disaggregate data points based on a specified frequency column empowers more granular and precise analysis. It transforms summary statistics back into their constituent elements, enabling deeper insights.

Base R Approaches for Row Repetition

R’s base functionalities offer several powerful ways to handle data manipulation, including row replication. While base R might sometimes appear less concise than tidyverse for certain operations, mastering these methods provides a fundamental understanding of how R processes data and can be highly efficient for specific tasks.

Using rep() and Row Indexing

One of the most intuitive base R methods involves using the rep() function in conjunction with row indexing. This approach leverages rep() to create a vector of row indices, where each index is repeated according to the value in your specified frequency column. You then use this vector to subset your original data frame, effectively replicating rows.

Sample Data df_base <- data.frame( Product = c("A", "B", "C"), Price = c(10, 20, 15), Quantity = c(2, 1, 3) ) Repeat rows using rep() and indexing The 'each' argument to rep() is key here, repeating each index as many times as specified in the 'Quantity' column. expanded_df_base <- df_base[rep(seq_len(nrow(df_base)), df_base$Quantity), ] Reset row names for cleanliness row.names(expanded_df_base) <- NULL View the result print(expanded_df_base) 

This method is straightforward and highly efficient for most common use cases. The rep(seq_len(nrow(df_base)), df_base$Quantity) part generates a sequence like 1, 1, 2, 3, 3, 3, which then directly indexes the data frame. It’s a classic base R idiom for this type of problem, demonstrating the flexibility of R’s indexing capabilities.

The lapply() and do.call() Combo

A slightly more advanced base R technique involves using lapply() to iterate over rows and do.call(rbind, …) to combine the results. This approach can be particularly useful if you need to apply additional transformations to each row before replication, or if you prefer a more functional programming style.

Sample Data (reusing df_base) df_base <- data.frame( Product = c("A", "B", "C"), Price = c(10, 20, 15), Quantity = c(2, 1, 3) ) Repeat rows using lapply and do.call(rbind, ...) list_of_replicated_rows <- lapply(1:nrow(df_base), function(i) { row_data <- df_base[i, ] num_repeats <- df_base$Quantity[i] if (num_repeats > 0) { return(row_data[rep(1, num_repeats), , drop = FALSE]) } else { return(NULL) Handle cases where quantity might be zero } }) expanded_df_lapply <- do.call(rbind, list_of_replicated_rows) Reset row names row.names(expanded_df_lapply) <- NULL View the result print(expanded_df_lapply) 

While lapply() and do.call(rbind, …) offer great flexibility, they can be less performant than direct indexing for very large datasets due to the overhead of creating and combining many small data frames. However, for moderate dataset sizes or when complex row-wise logic is needed, this combination provides a robust and clear solution. It highlights R’s capability for iterative processing and dynamic data frame construction.

Tidyverse Solutions: dplyr and tidyr

The tidyverse collection of packages, particularly dplyr for data manipulation and tidyr for data tidying, provides incredibly powerful and expressive tools for common data tasks. These packages are designed for consistency, readability, and performance, often simplifying complex operations into a few lines of code. For repeating rows, tidyr::uncount() stands out as the most idiomatic and efficient solution within the tidyverse ecosystem.

Leveraging tidyr::uncount()

When you need to repeat each row of a data frame the number of times specified in a column, tidyr::uncount() is the function specifically designed for this purpose. It takes your data and a column containing weights or counts, then expands the data frame accordingly. This function perfectly aligns with the principle of transforming ‘counted’ data back into individual observations, making it exceptionally clear and efficient for data expansion tasks. Its design prioritizes readability and ease of use, making complex data transformations straightforward.

Load necessary libraries library(dplyr) library(tidyr) Sample Data df_tidy <- data.frame( Item = c("Apple", "Banana", "Cherry"), Weight_g = c(150, 120, 5), Count = c(3, 2, 4) ) Repeat rows using tidyr::uncount() expanded_df_tidy <- df_tidy %>% uncount(Count) View the result print(expanded_df_tidy) 

This is arguably the most elegant and recommended way to achieve row replication in the tidyverse. Its clear syntax, uncount(column_name), directly communicates the intent: to “un-count” or expand based on the values in the Count column. It’s highly optimized and typically performs very well, even with large datasets, making it a go-to for modern R data workflows Question & Answer :

df <- data.frame(var1 = c('a', 'b', 'c'), var2 = c('d', 'e', 'f'), freq = 1:3) 

What is the simplest way to expand each row the first two columns of the data.frame above, so that each row is repeated the number of times specified in the column ‘freq’?

In other words, go from this:

df var1 var2 freq 1 a d 1 2 b e 2 3 c f 3 

To this:

df.expanded var1 var2 1 a d 2 b e 3 b e 4 c f 5 c f 6 c f 

Here’s one solution:

df.expanded <- df[rep(row.names(df), df$freq), 1:2] 

Result:

var1 var2 1 a d 2 b e 2.1 b e 3 c f 3.1 c f 3.2 c f