dplyr::bind_rows() / dplyr::bind_cols()

bind_rows(..., .id = NULL)
Returns: data.frame · Updated March 13, 2026 · Tidyverse
dplyr data-wrangling combine bind

bind_rows() and bind_cols() are dplyr functions for combining data frames. bind_rows() stacks data frames vertically (adding rows), while bind_cols() joins them horizontally (adding columns). These functions are faster than base R alternatives like rbind() and cbind().

Syntax

bind_rows(..., .id = NULL)

bind_cols(...)

Parameters

bind_rows()

ParameterTypeDefaultDescription
...data framesData frames to combine. Can also be a list of data frames.
.idstringNULLOptional column name to identify the source of each row

bind_cols()

ParameterTypeDefaultDescription
...data framesData frames to combine side by side. Must have same number of rows.

Examples

Basic bind_rows

Stack two data frames:

library(dplyr)

df1 <- data.frame(name = c("Alice", "Bob"), score = c(85, 92))
df2 <- data.frame(name = c("Charlie", "Diana"), score = c(78, 88))

bind_rows(df1, df2)

#   name score
# 1 Alice    85
# 2   Bob    92
# 3 Charlie    78
# 4  Diana    88

Using .id to track source

Identify which data frame each row came from:

df1 <- data.frame(name = "Alice", score = 85)
df2 <- data.frame(name = "Bob", score = 92)

bind_rows(a = df1, b = df2, .id = "source")

#   source  name score
# 1      a Alice    85
# 2      b   Bob    92

Combining data with different columns

bind_rows() handles mismatched columns gracefully:

df1 <- data.frame(name = "Alice", score = 85)
df2 <- data.frame(name = "Bob", score = 92, grade = "A")

bind_rows(df1, df2)

#   name score grade
# 1 Alice    85    NA
# 2   Bob    92     A

Basic bind_cols

Join columns side by side:

df1 <- data.frame(name = c("Alice", "Bob"))
df2 <- data.frame(score = c(85, 92), grade = c("B", "A"))

bind_cols(df1, df2)

#   name score grade
# 1 Alice    85     B
# 2   Bob    92     A

Common Patterns

Efficiently combining many data frames from a list

# Combine all data frames in a list
df_list <- list(df1, df2, df3, df4)
combined <- bind_rows(df_list)

Appending new data

# Add new observations to existing dataset
existing_data <- data.frame(name = c("Alice", "Bob"), score = c(85, 92))
new_data <- data.frame(name = "Charlie", score = 78)

updated <- bind_rows(existing_data, new_data)

Combining summary statistics

df <- data.frame(
  group = c("A", "A", "B", "B"),
  value = c(10, 15, 20, 25)
)

summary_a <- df |> filter(group == "A") |> summarise(mean = mean(value))
summary_b <- df |> filter(group == "B") |> summarise(mean = mean(value))

bind_rows(a = summary_a, b = summary_b, .id = "group")

#   group  mean
# 1     a  12.5
# 2     b  22.5

See Also