How to Sum Columns in R with 'colSums'

R Published Updated 2 mins read By Leon Wei
How to Sum Columns in R with 'colSums' cover image

Quick summary

Summarize this blog with AI

Introduction

colSums() produces one value per column. It is equivalent in purpose to apply(x, 2, sum) for an ordinary numeric matrix, not apply(x, 1, sum), which sums rows. Use a non-square, labelled fixture to make an axis mistake visible.

Tested with R 4.5.1. Run the following code blocks in order. All inputs are included.

Compare column and row totals

Rows are stores and columns are days. Each selected value is measured in the same units.

sales <- matrix(c(10, 20, 30, 40, 50, 60), nrow = 2, byrow = TRUE,
                dimnames = list(c("A", "B"), c("Mon", "Tue", "Wed")))
print(colSums(sales))  # Mon 50; Tue 70; Wed 90
print(rowSums(sales))  # A 60; B 150
stopifnot(identical(unname(colSums(sales)), c(50, 70, 90)))
stopifnot(isTRUE(all.equal(colSums(sales), apply(sales, 2, sum))))
stopifnot(length(colSums(sales)) == ncol(sales))

Changing a row operation to colSums changes the question. Compare equivalent operations before discussing speed. Never use a function name such as rowSums for a result variable.

Select measurement columns and handle missingness

A data frame may also contain numeric IDs or text labels. Select intended measurements rather than every numeric column.

records <- data.frame(store_id = c(101, 102), mon = c(10, 40),
                      tue = c(NA_real_, 50), wed = c(NA_real_, NA_real_))
amounts <- as.matrix(records[c("mon", "tue", "wed")])
complete <- colSums(amounts)
observed <- colSums(amounts, na.rm = TRUE)
observed_count <- colSums(!is.na(amounts))
observed[observed_count == 0] <- NA_real_
print(complete)  # 50 NA NA
print(observed)  # 50 50 NA
stopifnot(identical(unname(observed), c(50, 50, NA_real_)))

Tuesday has an observed subtotal of 50 but an unknown complete total. The explicit all-missing policy distinguishes “no observations” from zero. Counts make the difference reviewable.

Distinguish counts from amounts

Summing TRUE/FALSE conditions counts matches. To add qualifying amounts, retain their original values.

positive <- matrix(c(-1, 2, 3, 4, -5, 6), nrow = 2, byrow = TRUE)
count <- colSums(positive > 0)
selected <- positive
selected[selected <= 0] <- 0
amount <- colSums(selected)
print(count)   # 1 1 2
print(amount)  # 4 2 9
stopifnot(identical(count, c(1, 1, 2)), identical(amount, c(4, 2, 9)))

This fixture has no missing values. With missing measurements, define whether the output is an observed subtotal or a complete total before adding na.rm.

Preserve matrix shape and test emptiness

Selecting one column normally drops a matrix dimension; drop = FALSE preserves the two-dimensional input contract.

one_day <- sales[, "Mon", drop = FALSE]
stopifnot(identical(unname(colSums(one_day)), 50))
no_rows <- sales[FALSE, , drop = FALSE]
stopifnot(identical(unname(colSums(no_rows)), c(0, 0, 0)))
no_columns <- sales[, FALSE, drop = FALSE]
stopifnot(length(colSums(no_columns)) == 0)
wrong_type <- tryCatch(colSums(matrix(c("a", "2"), ncol = 1)), error = function(e) e)
stopifnot(inherits(wrong_type, "error"))

Zero-row input gives zero per column by the built-in sum convention; your reporting policy may require an explicit no-data state. Do not coerce arbitrary labels and ignore the resulting failures. The rowSums tutorial covers the complementary axis.

Primary references

Interview Prep

Begin Your SQL, Python, and R Journey

Master 230 interview-style coding questions and build the data skills needed for analyst, scientist, and engineering roles.

Related Articles

All Articles