Tests the MCAR assumption: that whether a value is missing is unrelated to any value in the data, observed or not.
Value
A list of class bricklayer_mcar: statistic,
df, p_value, n_patterns, n_used,
n_vars, iterations, mu, sigma, and
note (a caveat when the test is degenerate). With complete data
df is 0 and p_value is NA – there is nothing to
test.
Details
The assumption matters because it is what licenses the easy options. Dropping incomplete rows is unbiased under MCAR and biased otherwise; mean imputation understates variance under MCAR and distorts the centre as well otherwise. A small p-value here says the easy options are not available.
How it works
Rows are grouped by their pattern of missingness. If missingness is unrelated to the values, then each pattern's observed-variable means should agree with the overall estimates, up to sampling error. The statistic sums those disagreements, $$d^2 = \sum_j n_j (\bar{x}_j - \hat{\mu}_j)' \hat{\Sigma}_j^{-1} (\bar{x}_j - \hat{\mu}_j),$$ over the variables observed in pattern \(j\), and is compared with a chi-square distribution on \(\sum_j p_j - p\) degrees of freedom.
The overall \(\hat\mu\) and \(\hat\Sigma\) are the MAXIMUM-LIKELIHOOD estimates under multivariate normality WITH the missing data, obtained by expectation-maximisation – not the complete-case estimates, which would already embed the bias the test is looking for.
What it cannot do
A large p-value is NOT evidence that the data are MCAR; it is a failure to detect a departure, and the test has little power on small samples or with many patterns. The test also assumes multivariate normality, so on markedly non-normal columns a rejection may be telling you about the distribution rather than the missingness.
Neither this test nor any other can distinguish missing-at-random from missing-NOT-at-random, because that distinction depends on the values that were never observed. Only knowledge of how the data were collected settles it.
Collinear or constant columns are refused rather than worked around: the likelihood is degenerate there, and the EM step's eigenvalue floor would otherwise return a statistic governed by that floor instead of by the data.
References
Little RJA (1988). A test of missing completely at random for multivariate data with missing values. Journal of the American Statistical Association 83(404), 1198–1202. doi:10.1080/01621459.1988.10478722
Dempster AP, Laird NM, Rubin DB (1977). Maximum likelihood from incomplete data via the EM algorithm. Journal of the Royal Statistical Society B 39(1), 1–38.
See also
missingness_pattern() for the
patterns themselves,
missingness_summary() for the rates.
Examples
set.seed(1)
n <- 300
x <- stats::rnorm(n)
y <- x + stats::rnorm(n)
# Missing completely at random: a coin flip decides, so the test
# should not reject.
mcar <- data.frame(x = x, y = y)
mcar$y[sample(n, 90)] <- NA
mcar_test(mcar)
#> ── Little's MCAR test ────────────────────────────────────────────
#> ✓ no departure from MCAR detected
#>
#> statistic 1.094
#> df 1
#> p-value 0.296
#> patterns 2
#> variables 2
#> rows used 300
#> EM iterations 13
#>
#> Not evidence OF MCAR: a large p-value is a failure to detect a
#> departure, and this test has little power on small samples.
#> ──────────────────────────────────────────────────────────────────
# Missing depending on the OTHER, observed variable: not MCAR, and
# detectable, because the pattern's mean of x is shifted.
mar <- data.frame(x = x, y = y)
mar$y[x > 0.4] <- NA
mcar_test(mar)
#> ── Little's MCAR test ────────────────────────────────────────────
#> ✗ MCAR rejected: the missingness is related to the data
#>
#> statistic 180.118
#> df 1
#> p-value <2e-16
#> patterns 2
#> variables 2
#> rows used 300
#> EM iterations 69
#> ──────────────────────────────────────────────────────────────────
# Complete data has one pattern and nothing to test.
mcar_test(data.frame(a = x, b = y))$df
#> [1] 0
# A duplicated column makes the likelihood degenerate, and is refused.
dup <- mcar
dup$x2 <- dup$x
try(mcar_test(dup))
#> Error : the columns are collinear (or one is constant), so the multivariate normal likelihood Little's test is built on is degenerate. Drop the redundant column(s) first -- top_correlations() and drop_constant() will find them.
# The EM estimates are the ML ones: with no missingness they are the
# column means and the ML (1/n) covariance.
fit <- mcar_test(data.frame(a = x, b = y))
all.equal(fit$mu, c(mean(x), mean(y)), check.attributes = FALSE)
#> [1] TRUE