rguides

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

ParameterTypeDefaultDescription
xnumericREQUIREDA numeric vector or matrix
na.rmlogicalFALSEIf 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

See also