sd()
sd(x, na.rm = FALSE) The sd() function calculates the standard deviation of a numeric vector. Standard deviation is a fundamental statistical measure that quantifies the spread of data around the mean.
Syntax
sd(x, na.rm = FALSE)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | numeric | REQUIRED | A numeric vector or matrix |
na.rm | logical | FALSE | If TRUE, missing values are removed before computing |
Examples
Basic usage
x <- c(2, 4, 4, 4, 5, 5, 7, 9)
sd(x)
# [1] 2
A clean numeric vector is the ideal case, but real datasets frequently contain gaps. Like most R statistical functions, sd() propagates NA by default — if any element is missing, the entire result becomes NA. You must explicitly opt in to missing-value removal with na.rm = TRUE.
Handling missing values
x_with_na <- c(1, 2, NA, 4, 5)
sd(x_with_na)
# [1] NA
sd(x_with_na, na.rm = TRUE)
# [1] 1.825742
Once missing values are under control, the next practical question is how to compute standard deviations for subsets of your data — one value per group rather than one global number. Base R’s tapply() pairs a numeric vector with a grouping factor and applies sd() to each subset, returning a named vector of per-group results.
Standard deviation by group
Use tapply() to compute standard deviation for groups:
df <- data.frame(
group = c("A", "A", "A", "B", "B", "B"),
value = c(1, 2, 3, 10, 11, 12)
)
tapply(df$value, df$group, sd)
# A B
# 1.000000 1.000000
Raw standard deviations are measured in the same units as the original data, which makes them hard to compare across variables with different scales — is a standard deviation of 50 large or small? The coefficient of variation solves this by dividing the standard deviation by the mean, expressing variability as a proportion that is scale-independent and directly comparable across datasets.
Common patterns
Coefficient of variation
The coefficient of variation (CV) expresses standard deviation as a percentage of the mean:
cv <- function(x) sd(x) / mean(x) * 100
cv(c(10, 12, 14, 16, 18))
# [1] 24.27619
The coefficient of variation builds on sd(), but sometimes you need the variance itself — for ANOVA tables, variance-component models, or simply because a downstream formula expects variance rather than standard deviation. Since sd() is the square root of var(), you can recover the variance by squaring the result, which is more efficient than calling both functions separately on the same data.
Variance from standard deviation
x <- c(2, 4, 4, 4, 5, 5, 7, 9)
var_x <- sd(x) ^ 2
var_x
# [1] 4
sd() in practice
sd() computes the sample standard deviation: the square root of the unbiased sample variance. It uses n-1 in the denominator (Bessel’s correction), matching var(). For a single observation, sd() returns NA because division by zero (n-1 = 0) is undefined, check length(x) > 1 before calling if the input might have fewer than two elements.
sd() with na.rm = TRUE removes NA values before computing. Without it, any NA produces NA output. For per-column standard deviations on a data frame, sapply(df, sd) returns a named numeric vector. apply(m, 2, sd) does the same for a matrix.
Standardizing a vector (z-score normalization) uses sd() and mean(): (x - mean(x)) / sd(x) centers the data at zero and scales to unit variance. The scale() function does this automatically: scale(x) returns a column matrix with the standardized values. scale(x, center = FALSE) divides by sd without centering.
# Z-score standardization
x <- c(10, 20, 30, 40, 50)
z_manual <- (x - mean(x)) / sd(x) # manual calculation
z_scale <- as.vector(scale(x)) # built-in equivalent
round(z_manual, 3)
# [1] -1.265 -0.632 0.000 0.632 1.265
In statistical modeling, sd() appears in residual standard error calculation, confidence interval computation, and power analysis. sigma() on a model object returns the residual standard deviation directly. For reliable alternatives less sensitive to outliers, mad() (median absolute deviation) is the analogous measure.
sd() computes the sample standard deviation using n-1 in the denominator (Bessel’s correction). For the population standard deviation with n in the denominator, use sd(x) * sqrt((length(x)-1)/length(x)). sd() returns NA for input containing NA; use na.rm = TRUE to exclude missing values. For a vector of length 1, sd() returns NA, not 0.
sd() computes the sample standard deviation with n-1 in the denominator (Bessel’s correction), making it an unbiased estimator of the population standard deviation. For a vector of length 1, sd() returns NA — a single observation has no variance. For a vector with all identical values, sd() returns exactly 0.
na.rm = TRUE excludes missing values before computing. Without it, any NA in the input produces NA.
sd() is the square root of var(). For efficiency, compute v <- var(x) once and use sqrt(v) rather than calling both var() and sd() separately.
The coefficient of variation (relative standard deviation) is sd(x) / mean(x), expressed as a proportion, or multiplied by 100 for a percentage. This normalizes variability by the mean, making it comparable across datasets with different scales.
For reliable alternatives to sd() that are less sensitive to outliers, use mad(x) (median absolute deviation) or the interquartile range IQR(x). These are available in base R and are preferred when the data may contain extreme values.
# sd() vs mad() with an outlier
x_clean <- c(10, 12, 11, 13, 12)
x_outlier <- c(10, 12, 11, 13, 12, 100)
sd(x_clean) # [1] 1.14
sd(x_outlier) # [1] 35.9 — heavily inflated
mad(x_clean) # [1] 1.48
mad(x_outlier) # [1] 1.48 — barely affected