PERMANOVA
PERMANOVA (permutational multivariate analysis of variance) tests whether two or more groups differ significantly in their multivariate composition. It is the multivariate analogue of ANOVA, but instead of comparing means of a single variable, it compares the multivariate centroids of groups based on a distance matrix.
Because significance is assessed by permutation rather than by distributional assumptions, PERMANOVA works with any distance metric and makes no assumptions about normality. This makes it the standard hypothesis test for ecological and microbiome data analysed with Bray-Curtis or UniFrac distances.
How It Works
PERMANOVA partitions the total variance in a distance matrix into:
- Among-group variance: how different the groups are from each other
- Within-group variance: how variable samples are within each group
The test statistic (pseudo-F) is the ratio of among-group to within-group variance. Its significance is assessed by randomly permuting sample labels many times and recalculating pseudo-F each time. The p-value is the proportion of permutations that produced a pseudo-F as large as or larger than the observed value.
Running PERMANOVA in R
The adonis2() function in vegan is the current recommended implementation:
library(vegan)
data(dune)
data(dune.env)
# Compute distance matrix
dist_bray <- vegdist(dune, method = "bray")
# PERMANOVA: does Management explain community composition?
perm_result <- adonis2(dist_bray ~ Management,
data = dune.env,
permutations = 999)
perm_result
#> Df SumOfSqs R2 F Pr(>F)
#> Management 3 1.4686 0.34161 2.7672 0.005 **
#> Residual 16 2.8348 0.65839
#> Total 19 4.2990 1.00000
The R2 value is the effect size: the proportion of total compositional variance explained by the grouping variable. A significant p-value with a low R2 means the groups are statistically distinguishable but the grouping explains little of the overall variation.
Multiple explanatory variables
# Test multiple variables simultaneously
perm_multi <- adonis2(dist_bray ~ Management + Moisture,
data = dune.env,
permutations = 999,
by = "term") # Test each term sequentially
print(perm_multi)
Note that by = "term" tests variables sequentially, so the order matters. Use by = "margin" if you want each variable tested after accounting for all others (equivalent to Type III sums of squares).
Beta Dispersion
PERMANOVA is sensitive to differences in group dispersion (spread) as well as differences in group location (centroid). A significant result can therefore arise when one group is simply more variable than others, even if the centroids are in the same position.
Always run a beta dispersion test alongside PERMANOVA:
# Test homogeneity of multivariate dispersion
# H0: all groups have equal spread around their centroid
beta_disp <- betadisper(dist_bray, dune.env$Management)
permutest(beta_disp, permutations = 999)
# Visualise dispersion
plot(beta_disp, main = "Beta Dispersion by Management")
boxplot(beta_disp, main = "Distance to Group Centroid")
If beta dispersion is significant, the PERMANOVA result may be driven by differences in variability rather than differences in composition. Report both tests and discuss the distinction.
Pairwise Comparisons
A significant PERMANOVA tells you that at least one group differs from the others, but not which pairs. Pairwise PERMANOVA tests each pair of groups separately:
library(pairwiseAdonis)
pairwise_result <- pairwise.adonis(dist_bray,
dune.env$Management,
perm = 999)
print(pairwise_result)
# p-values are Bonferroni-corrected by default
With many groups, the number of pairwise comparisons grows quickly and correction for multiple testing becomes important.
Assumptions and Limitations
PERMANOVA assumes that samples are exchangeable under the null hypothesis, which broadly means that samples within groups are independent and that groups have similar multivariate dispersion. The independence assumption is violated by, for example, repeated measures or spatially autocorrelated samples.
PERMANOVA also requires a reasonable number of permutations to estimate p-values reliably. With very small groups (fewer than five samples per group), the number of possible permutations is limited and precise p-values cannot be obtained.
The minimum number of samples per group for a reliable test is roughly five, though more is always better. With fewer samples, treat p-values as approximate.
Reporting Results
A complete PERMANOVA result should report the distance metric, the number of permutations, R2, pseudo-F, and p-value, alongside the beta dispersion result:
"Community composition differed significantly among management types (PERMANOVA on Bray-Curtis distances, R2 = 0.34, pseudo-F = 2.76, p = 0.001, 999 permutations). Multivariate dispersion did not differ significantly between groups (betadisper, p = 0.18), supporting the interpretation that the PERMANOVA result reflects differences in community composition rather than differences in variability."
Exercise
Using the dune dataset:
- Test whether
ManagementandMoisturetogether explain community composition - Test each variable individually using
by = "term" - Check beta dispersion for
Management - Interpret the R2 values: which variable explains more variance?
Solution
library(vegan)
data(dune)
data(dune.env)
dist_bray <- vegdist(dune, method = "bray")
# 1 and 2. PERMANOVA with both variables, term-by-term
perm_result <- adonis2(dist_bray ~ Management + Moisture,
data = dune.env,
permutations = 999,
by = "term")
print(perm_result)
# R2 for each term shows its relative contribution
# 3. Beta dispersion for Management
beta_disp <- betadisper(dist_bray, dune.env$Management)
permutest(beta_disp, permutations = 999)
plot(beta_disp)
# 4. Interpretation
# Compare R2 values for Management vs Moisture
# A significant beta dispersion would require cautious interpretation
# of the PERMANOVA result for that variable