Analistable

How to merge data frames in R

By the Analistable team · Updated · 2 min read

In base R, merge(x, y, by = "id") does an inner join; add all.x = TRUE for a left join or all = TRUE for a full join. In dplyr, use left_join(x, y, by = join_by(id)), inner_join, full_join or anti_join. To stack data frames with the same columns, use rbind() or dplyr::bind_rows().

Part of our guide: How to merge data in pandas, R and SQL

Example data

customers <- data.frame(
  customer_id = c("C-101", "C-102", "C-103"),
  name = c("Bakery Lune", "Hart & Co", "Nordic Supply")
)
orders <- data.frame(
  order_id = c("O-9001", "O-9002", "O-9003", "O-9004"),
  customer_id = c("C-101", "C-103", "C-101", "C-104"),
  amount = c(120, 75, 80, 60)
)

Base R: merge()

merge() arguments by join type
JoinCode
Innermerge(orders, customers, by = "customer_id")
Leftmerge(orders, customers, by = "customer_id", all.x = TRUE)
Rightmerge(orders, customers, by = "customer_id", all.y = TRUE)
Fullmerge(orders, customers, by = "customer_id", all = TRUE)
Different key namesmerge(x, y, by.x = "cust", by.y = "customer_id")

merge() sorts the result by the key columns by default; pass sort = FALSE to keep the original order.

dplyr joins

library(dplyr)

orders |> left_join(customers, by = join_by(customer_id))
customers |> anti_join(orders, by = join_by(customer_id))   # never ordered
orders |> inner_join(customers, by = join_by(customer_id),
                     relationship = "many-to-one")

join_by() (dplyr 1.1+) also handles different names (join_by(cust == customer_id)) and inequality joins. relationship = "many-to-one" raises an error if customers has duplicate keys.

left_join result
order_idcustomer_idamountname
O-9001C-101120Bakery Lune
O-9002C-10375Nordic Supply
O-9003C-10180Bakery Lune
O-9004C-10460NA

Stacking data frames

  • rbind(jan, feb) — columns must have the same names (order can differ).
  • dplyr::bind_rows(jan, feb, .id = "source") — fills missing columns with NA and adds a source column.
  • Many files: bind_rows(lapply(list.files("sales", full.names = TRUE), read.csv)).

The same joins in pandas and SQL are mapped side by side in merging data in pandas, R and SQL.

Common problems

Problems when merging in R
SymptomCauseFix
More rows than expectedDuplicate keys in the lookup tableCheck with `anyDuplicated(customers$customer_id)`; set relationship in dplyr
Columns named name.x and name.yBoth tables have a non-key column with the same nameRename first, or set suffixes = c("_order", "_cust")
No matchesKey is a factor in one table and character in the other, or has spacesConvert with as.character() and trimws()
Row order changedmerge() sorts by key by defaultUse sort = FALSE or dplyr joins

Frequently asked questions

How do I do a left join in R?
Use merge(x, y, by = "key", all.x = TRUE) in base R, or left_join(x, y, by = join_by(key)) in dplyr.
How do I merge more than two data frames in R?
Chain joins with the pipe, or use Reduce(function(a, b) merge(a, b, by = "key"), list(df1, df2, df3)).
What's the difference between merge and rbind?
merge matches rows on key columns; rbind stacks rows of data frames with the same columns.

Related guides