Quick summary
Summarize this blog with AI
sum returns one total
sum() reduces its supplied values to one number. A second numeric argument is another value to add, not a row or column selector. Use rowSums() and colSums() when you need separate totals along an axis. Run the examples sequentially with base R 4.5.1.
Add vectors and additional values
amounts <- c(10, 20, 30)
stopifnot(sum(amounts) == 60)
stopifnot(sum(amounts, 2) == 62)
print(sum(amounts, c(4, 5))) # 69
stopifnot(sum(numeric(0)) == 0)
The values may come from multiple numeric or logical vectors. An empty numeric input sums to zero. A character vector or an arbitrary list is not interchangeable with a numeric vector; check the input type instead of silently coercing text and dropping failed conversions.
Choose the axis on a non-square matrix
sales <- matrix(c(10, 20, 30, 40, 50, 60), nrow = 2, byrow = TRUE,
dimnames = list(c("Store_A", "Store_B"),
c("Monday", "Tuesday", "Wednesday")))
print(sales)
print(sum(sales)) # 210
print(sum(sales, 2)) # 212: the grand total plus 2
print(rowSums(sales)) # Store_A 60; Store_B 150
print(colSums(sales)) # Monday 50; Tuesday 70; Wednesday 90
stopifnot(sum(sales) == 210, sum(sales, 2) == 212)
stopifnot(identical(unname(rowSums(sales)), c(60, 150)))
stopifnot(identical(unname(colSums(sales)), c(50, 70, 90)))
The two stores and three days make an axis mistake visible: row totals have length two, while column totals have length three. All three aggregation choices conserve the same grand total when no values are missing. For mixed data frames, select the intended numeric measurement columns before aggregating.
State what missing values mean
observed <- c(10, NA_real_, 30)
stopifnot(is.na(sum(observed)))
stopifnot(sum(observed, na.rm = TRUE) == 40)
stopifnot(sum(c(NA_real_, NA_real_), na.rm = TRUE) == 0)
observed_total <- function(x) {
stopifnot(is.numeric(x))
if (all(is.na(x))) return(NA_real_)
sum(x, na.rm = TRUE)
}
stopifnot(observed_total(observed) == 40)
stopifnot(is.na(observed_total(c(NA_real_, NA_real_))))
stopifnot(is.na(observed_total(numeric(0))))
The helper deliberately treats both an empty input and an all-missing input as “no observations,” returning NA. That is an application policy, not the built-in definition of sum. Omitting NA gives an observed subtotal; it does not recover the unknown complete total. Also inspect nonfinite values: na.rm = TRUE does not remove positive or negative infinity.
Distinguish a count from an amount
payments <- c(50, 150, 250, NA_real_)
qualifies <- !is.na(payments) & payments > 100
print(sum(qualifies)) # 2 payments
print(sum(payments[qualifies])) # 400 currency units
stopifnot(sum(qualifies) == 2, sum(payments[qualifies]) == 400)
stopifnot(sum(c(TRUE, FALSE, TRUE)) == 2)
stopifnot(is.na(sum(c(TRUE, NA))))
Logical TRUE contributes one and FALSE contributes zero. Summing a condition counts matches; summing values selected by that condition adds the amounts. A missing payment is excluded explicitly in this example, so both results describe known payments only.
Validate the input and the result
bad_type <- tryCatch(sum(c("10", "20")), error = function(e) e)
stopifnot(inherits(bad_type, "error"))
stopifnot(is.infinite(sum(c(1, Inf), na.rm = TRUE)))
stopifnot(is.nan(sum(c(Inf, -Inf), na.rm = TRUE)))
stopifnot(sum(rowSums(sales)) == sum(colSums(sales)))
Floating-point totals can have rounding error; compare calculated decimal results with an appropriate tolerance rather than assuming exact equality. The integer-valued teaching examples above are exactly representable. For repeated per-record totals and explicit missing-data reporting, see the rowSums tutorial.