SyntaxStudy
Sign Up
R Merging, Reshaping, and Applying Functions to Data Frames
R Beginner 1 min read

Merging, Reshaping, and Applying Functions to Data Frames

Combining data frames by columns (cbind()) or rows (rbind()) is straightforward when the dimensions match. More powerful relational joins are available through merge(), which performs inner, left, right, and full outer joins by specifying by, all.x, and all.y arguments. The dplyr package's join verbs (left_join(), inner_join(), etc.) offer a cleaner interface and are covered in the dplyr topic. Reshaping transforms data between wide format (one row per subject, multiple measurement columns) and long format (one row per observation). Base R provides reshape() for this purpose, but the tidyr package's pivot_longer() and pivot_wider() are far more intuitive. Long format is typically required by ggplot2 and many modelling functions, so knowing how to reshape is a critical skill. The apply family of functions applies a function over the margins of a matrix or over elements of a list or data frame. apply() works on matrices row-wise or column-wise, lapply() returns a list, sapply() simplifies the result to a vector or matrix when possible, and tapply() computes group summaries. These functions are the base-R precursors to dplyr's group_by() / summarise() workflow and are still widely used in production code.
Example
# cbind / rbind
left  <- data.frame(id = 1:3, x = c(10, 20, 30))
right <- data.frame(id = 1:3, y = c("a", "b", "c"))
cbind(left, right[ , -1])            # add column y

extra_row <- data.frame(id = 4, x = 40)
rbind(left, extra_row)               # append a row

# merge() — SQL-style joins
orders <- data.frame(
    cust_id = c(1, 2, 2, 3),
    amount  = c(100, 200, 150, 300)
)
customers <- data.frame(
    cust_id = c(1, 2, 4),
    name    = c("Alice", "Bob", "Dave")
)
merge(orders, customers, by = "cust_id")             # inner join
merge(orders, customers, by = "cust_id", all.x = TRUE) # left join
merge(orders, customers, by = "cust_id", all = TRUE)   # full outer

# apply family
m <- matrix(1:12, nrow = 3)
apply(m, 1, sum)   # row sums    -> length 3
apply(m, 2, sum)   # column sums -> length 4

df <- data.frame(a = c(1,2,3), b = c(4,5,6), c = c(7,8,9))
sapply(df, mean)   # mean of each column -> named numeric vector
lapply(df, range)  # min/max of each column -> named list

# tapply — grouped summary
scores <- c(85, 90, 78, 92, 88, 76)
groups <- c("A", "B", "A", "B", "A", "B")
tapply(scores, groups, mean)   # mean score per group

# do.call — assemble a data frame from a list of rows
rows <- list(
    data.frame(x = 1, y = "one"),
    data.frame(x = 2, y = "two")
)
do.call(rbind, rows)