rguides

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

ParameterTypeDefaultDescription
xnumericREQUIREDA numeric vector or matrix
ynumericNULLOptional second vector for pairwise variance
na.rmlogicalFALSEIf TRUE, missing values are removed before computing
usecharacter”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.

See also