var()
var(x, y = NULL, na.rm = FALSE, use) The var() function calculates the variance of a numeric vector. Variance is a fundamental statistical measure that quantifies the spread of data around the mean.
Syntax
var(x, y = NULL, na.rm = FALSE, use)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | numeric | REQUIRED | A numeric vector or matrix |
y | numeric | NULL | Optional second vector for pairwise variance |
na.rm | logical | FALSE | If TRUE, missing values are removed before computing |
use | character | ”everything” | How to handle missing values: “everything”, “all.obs”, “complete.obs”, “pairwise.complete.obs” |
Examples
Basic usage
x <- c(2, 4, 4, 4, 5, 5, 7, 9)
var(x)
# [1] 4.571429
Handling missing values
var() defaults to na.rm = FALSE, meaning a single NA in the input propagates to an NA result. This is the statistically conservative choice: if some values are unknown, the variance of the set is also unknown. Setting na.rm = TRUE tells R to compute the variance from only the observed values, which is appropriate when missingness is random and you are comfortable estimating from the available data.
x_with_na <- c(1, 2, NA, 4, 5)
# Without na.rm - returns NA
var(x_with_na)
# [1] NA
# With na.rm = TRUE
var(x_with_na, na.rm = TRUE)
# [1] 3.7
Variance of a matrix
Passing a numeric matrix to var() returns the full variance-covariance matrix: diagonal entries are column variances, off-diagonal entries are pairwise covariances. This is identical to calling cov() on the same matrix and is the standard way to get a covariance matrix for multivariate analysis, principal components, or linear model diagnostics without loading extra packages.
# var() can compute variance-covariance matrix
m <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2)
var(m)
# [,1] [,2]
# [1,] 2.333333 2.333333
# [2,] 2.333333 2.333333
Pairwise variance
Calling var(x, y) with two vectors of equal length computes their covariance, not the variance of a single vector. Covariance measures how two variables move together: positive values mean they tend to increase together, negative values mean one tends to decrease as the other increases. This is the foundation for correlation and regression slope calculations.
# Variance between two vectors
var(c(1, 2, 3), c(4, 5, 6))
# [1] 0.5
Common patterns
Standard deviation from variance
Standard deviation is simply the square root of variance: sd(x) is sqrt(var(x)) and the two functions share the same na.rm behavior. If you need both the variance and the standard deviation for the same data, compute var() once and take sqrt() of the result — calling sd() separately would repeat the variance calculation unnecessarily and double the work for large vectors.
x <- c(2, 4, 4, 4, 5, 5, 7, 9)
sd_x <- sqrt(var(x))
sd_x
# [1] 2
Variance by group
tapply() pairs naturally with var() for grouped summaries. The combination tapply(df$value, df$group, var) computes the variance within each level of the grouping factor and returns a named vector — one variance per group. This is the base R equivalent of dplyr::group_by() %>% summarise(var(value)) and works without any package dependencies.
Use tapply() to compute variance 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, var)
# A B
# 1.000000 1.000000
var() and sd() in practice
var() computes the sample variance using the unbiased estimator with n-1 denominator (Bessel’s correction). This is the standard choice for estimating population variance from a sample. If you need population variance (divide by n), use var(x) * (length(x)-1) / length(x) or work with the sum of squared deviations directly. The tidyverse does not have a built-in population variance function; both var() and sd() use the sample convention.
var() of a single value (or a vector with all values identical) returns NA for length-1 inputs and 0 for constant vectors, but length-1 inputs return NA because the sample variance is undefined with only one observation (dividing by n-1 = 0).
For variance across multiple columns in a data frame, sapply(df, var) returns a named vector of variances. var(matrix) computes the covariance matrix, not a vector of column variances, use apply(m, 2, var) for column-wise variance on a matrix.
var() and sd() accept na.rm = TRUE to skip missing values. For correlation and covariance between two variables, cov(x, y) and cor(x, y) generalize var(). cov(x, x) is identical to var(x), and cor(x, y) == cov(x, y) / (sd(x) * sd(y)).
var() computes the sample variance using n-1 (Bessel’s correction). For a vector with all identical values, var() returns 0. For a length-1 vector, it returns NA. Pass a matrix to get the variance-covariance matrix of all column pairs. na.rm = TRUE excludes missing values. The population variance (dividing by n) is var(x) * (n-1)/n where n = length(x), R does not provide a built-in for it.
var() uses n-1 (Bessel’s correction) in the denominator, making it an unbiased estimator of the population variance from a sample. For a vector of length 1, var() returns NA; for a vector with all identical values, it returns exactly 0.
Called on a matrix, var(m) returns the variance-covariance matrix of the columns, each diagonal element is the variance of a column, and off-diagonal elements are covariances. This is equivalent to cov(m). For the correlation matrix (covariances scaled to [-1, 1]), use cor(m).
na.rm = TRUE excludes NA values before computing. Note that removing NA values changes the effective sample size — if different columns have different patterns of missing values, the variance-covariance matrix may be estimated from different subsets of rows.
The standard deviation is sqrt(var(x)), which equals sd(x). For computational efficiency when you need both, compute var() once and take the square root rather than calling sd() separately.
Comparing group variance to detect heteroscedasticity
# Test scores from two teaching methods
method_a <- c(72, 78, 74, 76, 75, 73, 77)
method_b <- c(55, 85, 60, 90, 50, 88, 62)
# Variance within each group
var(method_a)
# [1] 4.666667
var(method_b)
# [1] 299.3333
# Ratio of variances (F-test statistic)
f_stat <- var(method_b) / var(method_a)
f_stat
# [1] 64.14286
# Levene's test with car package
# car::leveneTest(c(method_a, method_b) ~ rep(c("A", "B"), each = 7))
Method A produces scores tightly clustered around 75 with a variance of only 4.7, while method B has extreme spread with a variance of 299 — a ratio of 64 to 1. Such a large discrepancy signals heteroscedasticity, which violates the equal-variance assumption of standard t-tests and ANOVA. When group variances differ by more than a factor of 3 or 4, consider Welch’s t-test (which does not assume equal variances) or a non-parametric alternative like the Mann-Whitney U test.