NA in Calculations and Aggregations
Control NA behavior in mean(), sum(), and other aggregate functions.
NA in Calculations and Aggregations is a free R Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, and your progress syncs across the web and the CoddyKit app. The R Academy course includes 4 lessons in total.
The na.rm Parameter
Most R aggregation functions accept a na.rm argument (NA remove). When set to TRUE, the function ignores NA values before computing the result. By default, na.rm = FALSE, so NAs propagate.
scores <- c(88, NA, 72, 95, NA, 81, 67)
cat('With na.rm=FALSE (default):
')
cat(' mean:', mean(scores), '
') # NA
cat(' sum: ', sum(scores), '
') # NA
cat('With na.rm=TRUE:
')
cat(' mean:', mean(scores, na.rm = TRUE), '
') # 80.6
cat(' sum: ', sum(scores, na.rm = TRUE), '
') # 403mean() with na.rm
mean(x, na.rm = TRUE) computes the arithmetic mean of the non-missing values. The denominator is the count of present values, not the total length.
temperatures <- c(22.1, NA, 19.8, 25.1, NA, 17.3, 20.0)
cat('Total elements:', length(temperatures), '
')
cat('Present elements:', sum(!is.na(temperatures)), '
')
cat('Mean (na.rm=TRUE):', mean(temperatures, na.rm = TRUE), '
')
# Manual verification
cat('Manual mean:', sum(temperatures, na.rm=TRUE) / sum(!is.na(temperatures)), '
')sum() with na.rm
sum(x, na.rm = TRUE) adds only the non-NA values. This is essential for counting TRUE values in a logical vector that may contain NAs, or computing totals from incomplete data.
sales_daily <- c(1200, NA, 980, 1450, NA, 1100, 890)
cat('Sum (default):', sum(sales_daily), '
') # NA
cat('Sum (na.rm): ', sum(sales_daily, na.rm = TRUE), '
') # 5620
# Count observations meeting a condition (NA-safe)
cat('Days over 1000:', sum(sales_daily > 1000, na.rm = TRUE), '
')min() and max() with na.rm
min() and max() also have the na.rm parameter. Without it, a single NA in the input causes the function to return NA. With na.rm = TRUE, the extremes of the present values are returned.
blood_pressure <- c(120, NA, 135, 118, NA, 142, 125, NA, 130)
cat('Max BP (default):', max(blood_pressure), '
') # NA
cat('Max BP (na.rm): ', max(blood_pressure, na.rm = TRUE), '
') # 142
cat('Min BP (na.rm): ', min(blood_pressure, na.rm = TRUE), '
') # 118
cat('Range (na.rm): ', range(blood_pressure, na.rm = TRUE), '
')var() and sd() with na.rm
Variance (var()) and standard deviation (sd()) also support na.rm. They compute the statistic using only the non-missing observations, automatically adjusting the degrees of freedom.
exam_scores <- c(78, 85, NA, 92, 68, 75, NA, 88, 91, NA)
n_valid <- sum(!is.na(exam_scores))
cat('Valid observations:', n_valid, '
')
cat('Mean: ', round(mean(exam_scores, na.rm = TRUE), 2), '
')
cat('SD: ', round(sd(exam_scores, na.rm = TRUE), 2), '
')
cat('Var: ', round(var(exam_scores, na.rm = TRUE), 2), '
')median() and quantile() with na.rm
median() and quantile() are often more robust to outliers than the mean, but they also need na.rm = TRUE to handle missing values correctly.
incomes <- c(45000, NA, 52000, 48000, NA, 210000, 51000, NA, 49000)
cat('Observations:', sum(!is.na(incomes)), '
')
cat('Median income:', median(incomes, na.rm = TRUE), '
')
cat('Mean income: ', mean(incomes, na.rm = TRUE), '
') # pulled up by 210000
cat('25th pctile: ', quantile(incomes, 0.25, na.rm = TRUE), '
')
cat('75th pctile: ', quantile(incomes, 0.75, na.rm = TRUE), '
')prod() and cumsum() with na.rm
prod(x, na.rm = TRUE) computes the product of non-NA values. Cumulative functions like cumsum() do NOT have na.rm — NAs propagate from the first missing value onwards.
growth_rates <- c(1.05, NA, 1.03, 1.08, NA, 1.02)
cat('Product of rates:', prod(growth_rates, na.rm = TRUE), '
')
# cumsum propagates NAs
values <- c(10, 20, NA, 40, 50)
cat('cumsum (with NA):', cumsum(values), '
')
# Workaround: replace NA first
filled <- replace(values, is.na(values), 0)
cat('cumsum (NA=0): ', cumsum(filled), '
')na.rm in Apply Functions
When using apply() over rows or columns of a matrix, you can pass na.rm = TRUE to the function using .... This computes aggregates while ignoring NAs.
m <- matrix(c(88,NA,72, 95,81,NA, 67,75,90), nrow = 3)
cat('Matrix:
'); print(m)
# Row means ignoring NAs
cat('Row means (na.rm=TRUE):', apply(m, 1, mean, na.rm = TRUE), '
')
# Col means ignoring NAs
cat('Col means (na.rm=TRUE):', apply(m, 2, mean, na.rm = TRUE), '
')rowSums() / colSums() with na.rm
rowSums() and colSums() have their own na.rm parameter (not passed via ...). Using na.rm = TRUE makes them treat NA as 0 in sums.
sales <- matrix(c(100,NA,80, NA,90,70, 110,85,NA), nrow = 3)
cat('Sales matrix:
'); print(sales)
cat('Row sums (na.rm=F):', rowSums(sales), '
') # NAs propagate
cat('Row sums (na.rm=T):', rowSums(sales, na.rm = TRUE), '
')
cat('Col means (na.rm=T):', colMeans(sales, na.rm = TRUE), '
')Comparison: na.rm=FALSE vs TRUE
Understanding when to use na.rm = TRUE vs FALSE is about your analysis intent: FALSE ensures you know data is incomplete; TRUE computes best-estimate statistics from available data.
# Always check: how much data is missing BEFORE using na.rm=TRUE
collected <- c(78, NA, 85, NA, 91, 74, NA, 88, 82, NA)
pct_missing <- mean(is.na(collected)) * 100
cat('Missing:', round(pct_missing, 1), '% of data
')
if (pct_missing < 20) {
cat('Acceptable: computing mean with na.rm=TRUE
')
cat('Mean:', round(mean(collected, na.rm = TRUE), 2), '
')
} else {
cat('Too much missing data — investigate before computing
')
}na.rm in User Functions
When writing your own aggregation functions, include an na.rm parameter and pass it through to base R functions. This makes your functions consistent with R's conventions.
# Custom function with na.rm support
cv <- function(x, na.rm = FALSE) {
# Coefficient of Variation = SD / mean
s <- sd(x, na.rm = na.rm)
m <- mean(x, na.rm = na.rm)
return(s / m)
}
readings <- c(22.1, NA, 19.8, 25.1, NA, 17.3, 20.0)
cat('CV (na.rm=FALSE):', cv(readings), '
') # NA
cat('CV (na.rm=TRUE): ', round(cv(readings, na.rm = TRUE), 4), '
')Quick Check
What does mean(c(10, 20, NA, 40), na.rm = TRUE) return?
Recap: NA in Calculations
Excellent! Key takeaways from this lesson:
- Most aggregation functions (
mean,sum,min,max,sd, etc.) have ana.rmparameter na.rm = FALSE(default) means NA propagates — if any value is NA, the result is NAna.rm = TRUEignores NAs and computes the statistic from present values only- The denominator for
mean(na.rm=TRUE)is the count of non-NA values, not total length - Always check the proportion of missing data before computing statistics with
na.rm=TRUE - Include
na.rmin your own aggregation functions to follow R convention
# Complete summary with na.rm
data_vec <- c(55, NA, 72, 88, NA, 61, 79, NA, 93, 68)
cat('N valid:', sum(!is.na(data_vec)), '
')
cat('Mean: ', round(mean(data_vec, na.rm=TRUE), 2), '
')
cat('Median:', median(data_vec, na.rm=TRUE), '
')
cat('SD: ', round(sd(data_vec, na.rm=TRUE), 2), '
')
cat('Min: ', min(data_vec, na.rm=TRUE), '
')
cat('Max: ', max(data_vec, na.rm=TRUE), '
')Learn R with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 43
- Lessons
- 159
Frequently Asked Questions
Is the “NA in Calculations and Aggregations” lesson free?
Yes — any 3 lessons of the R Academy learning path, including “NA in Calculations and Aggregations”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The R Academy course includes 4 lessons in total.
What will I learn in “NA in Calculations and Aggregations”?
Control NA behavior in mean(), sum(), and other aggregate functions. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start R Academy?
No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
How long does the “NA in Calculations and Aggregations” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this R Academy lesson?
Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Understanding NA in R
- Detecting and Counting Missing Values
- Removing and Replacing NA Values
- NA in Calculations and Aggregations