Q&A 15 How do you test for differences in community composition using PERMANOVA?

15.1 Explanation

PERMANOVA (Permutational Multivariate Analysis of Variance) is used to test whether beta diversity significantly differs between groups.

It operates on a dissimilarity matrix (e.g., Bray-Curtis) and partitions variation based on experimental factors like treatment group or location.

This Q&A applies PERMANOVA to Bray-Curtis distances computed from OTU abundances.

15.2 Python Code

import pandas as pd
from skbio.diversity import beta_diversity
from skbio.stats.distance import permanova
from skbio import DistanceMatrix

# Load data
otu_df = pd.read_csv("data/otu_table_filtered.tsv", sep="\t", index_col=0).T
meta_df = pd.read_csv("data/sample_metadata.tsv", sep="\t")

# Compute Bray-Curtis distance matrix
bray_dm = beta_diversity("braycurtis", otu_df.values, ids=otu_df.index)

# Format metadata
meta_df = meta_df.set_index("sample_id").loc[otu_df.index]

# Run PERMANOVA
result = permanova(distance_matrix=bray_dm, grouping=meta_df["group"], permutations=999)
print(result)

15.3 R Code

library(vegan)
library(tidyverse)

otu_df <- read.delim("data/otu_table_filtered.tsv", row.names = 1)
meta_df <- read.delim("data/sample_metadata.tsv")

# Bray-Curtis distance
otu_t <- t(otu_df)
bray <- vegdist(otu_t, method = "bray")

# Match metadata
meta_df <- meta_df %>% filter(sample_id %in% rownames(otu_t)) %>% column_to_rownames("sample_id")

# Run PERMANOVA (adonis)
adonis_res <- adonis2(bray ~ group, data = meta_df, permutations = 999)

adonis_res
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 999

adonis2(formula = bray ~ group, data = meta_df, permutations = 999)
         Df SumOfSqs      R2      F Pr(>F)
Model     1  0.03744 0.08118 0.7068  0.876
Residual  8  0.42380 0.91882              
Total     9  0.46124 1.00000