SACAT analyzes microbiome counts to separate evidence for differences
in structural absence (SA) from differences in relative abundance
conditional on presence (RA). Sequencing depth enters the model because
a zero can reflect either absence or nondetection. RA effects are
standardized over covariates and centered against a reference from other
eligible taxa. The primary omnibus p-value is
min(1, 2 * min(p_SA, p_RA)). Benjamini–Hochberg (BH)
adjustment is applied separately to each result family.
Install SACAT from GitHub using R 4.6.0 or later and a C++ compiler.
The Global Enteric Multicenter Study collected stool samples from children with diarrhea and controls without diarrhea. Here we use controls from Bangladesh, The Gambia, Kenya, and Mali to compare 191 infants aged 1–11 months with 137 children aged 24–58 months.
data("gems_microbiome", package = "SACAT")
dim(gems_microbiome)
#> [1] 41 328
table(gems_microbiome$group)
#>
#> Infant Older
#> 191 137The counts assay contains raw 16S counts for the 41
named bacterial genera detected in at least 20% of the 328 children. The
reads column in colData(gems_microbiome) gives
each sample’s library size from the full count table, before genus
selection. Use this original depth when fitting a subset of taxa.
The model compares older children with infants while adjusting for
country. sacat_se() reads the counts and sample annotations
from the SummarizedExperiment. Use sacat() for
a count matrix and metadata frame.
fit <- sacat_se(
gems_microbiome,
formula = ~ country + group,
group = "group",
reference = "Infant",
library_size = "reads",
store_plot_data = TRUE
)
#> Warning: Structural-absence inference returned with numerical warnings for 2
#> taxon/taxa; inspect diagnostics$warning_structural_absence.
fit
#> SACAT fit
#> Samples: 328; taxa: 41; retained taxa: 41
#> Contrast: Older - Infant
#> Structural results returned: 37/41
#> Regular structural score tests: 37/41
#> Nonregular structural results: 0/41
#> Structural-absence discoveries (BH-adjusted p <= 0.05): 11
#> Relative-abundance tests formed: 41/41
#> Relative-abundance discoveries (BH-adjusted p <= 0.05): 17
#> Omnibus discoveries (BH-adjusted p <= 0.05): 21
#> Results: x$results; formation details: x$diagnosticsWe can inspect the adjusted p-values for three genera after fitting all 41. Each column uses BH adjustment across the full set of genera.
genera <- c("Haemophilus", "Lactobacillus", "Faecalibacterium")
columns <- c("p_adj_structural_absence", "p_adj_relative_abundance",
"p_adj_omnibus")
rows <- match(genera, fit$results$taxon)
p_values <- fit$results[rows, columns]
p_values[] <- lapply(p_values, function(p) sprintf("%.3g", p))
knitr::kable(
data.frame(Genus = genera, p_values),
col.names = c("Genus", "SA", "RA", "Omnibus"),
row.names = FALSE
)| Genus | SA | RA | Omnibus |
|---|---|---|---|
| Haemophilus | 0.022 | 0.158 | 0.0164 |
| Lactobacillus | 0.073 | 0.000291 | 0.000388 |
| Faecalibacterium | 3.1e-07 | 9.54e-05 | 3.2e-07 |
In older children, Haemophilus showed evidence of lower
structural absence (SA only). Lactobacillus showed lower
relative abundance conditional on presence (RA only). For
Faecalibacterium, older children had both lower structural
absence and higher relative abundance conditional on presence. The
omnibus test detected all three associations. For other genera,
fit$results provides the effect estimates and p-values, and
fit$diagnostics reports test availability and numerical
warnings.
A. Component evidence. Filled points mark BH-adjusted p-values at or below 0.05. Positive signed statistics indicate higher structural absence or higher reference-adjusted conditional abundance in older children. Stars beside the genus names summarize the adjusted omnibus p-values.
B. Detection and zero sources. The blue portion gives the fraction of children in whom the genus was detected. The other two portions divide the observed zeros between estimated structural absence (SA) and nondetection despite presence (ND), using fitted probabilities.
C. Abundance. Each point is a positive observed count divided by that sample’s full library size, expressed as a percentage. Diamonds show fitted abundance conditional on presence, obtained by averaging fitted log abundance over the same country profiles for each age group and exponentiating. The log ratio of the diamonds gives the raw abundance contrast. The RA test centers this contrast against the reference estimated from other genera.
Pop M, Walker AW, Paulson J, et al. (2014). Diarrhea in young children from low-income countries leads to large-scale alterations in intestinal microbiota composition. Genome Biology 15, R76. Study
The counts and sample annotations come from the Bioconductor
experiment data package msd16s. See
?gems_microbiome for the selection criteria.
session <- sessionInfo()
for (field in intersect(c("BLAS", "LAPACK"), names(session))) {
session[[field]] <- basename(session[[field]])
}
print(session)
#> R version 4.6.2 (2026-10-29)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 LTS
#>
#> Matrix products: default
#> BLAS: libblas.so.3
#> LAPACK: libopenblasp-r0.3.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats4 stats graphics grDevices utils datasets methods
#> [8] base
#>
#> other attached packages:
#> [1] SummarizedExperiment_1.43.0 Biobase_2.73.2
#> [3] GenomicRanges_1.65.4 Seqinfo_1.3.2
#> [5] IRanges_2.47.5 S4Vectors_0.51.10
#> [7] BiocGenerics_0.59.13 generics_0.1.4
#> [9] MatrixGenerics_1.25.0 matrixStats_1.5.0
#> [11] SACAT_0.99.2 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] Matrix_1.7-6 jsonlite_2.0.0 compiler_4.6.2
#> [4] BiocManager_1.30.27 Rcpp_1.1.2 jquerylib_0.1.4
#> [7] statmod_1.5.2 yaml_2.3.12 fastmap_1.2.0
#> [10] lattice_0.23-1 XVector_0.53.0 R6_2.6.1
#> [13] S4Arrays_1.13.2 knitr_1.52 DelayedArray_0.39.8
#> [16] maketools_1.3.2 bslib_0.12.0 rlang_1.3.0
#> [19] cachem_1.1.0 xfun_0.62 sass_0.4.10
#> [22] sys_3.4.3 otel_0.3.0 SparseArray_1.13.5
#> [25] cli_3.6.6 digest_0.6.39 grid_4.6.2
#> [28] lifecycle_1.0.5 evaluate_1.0.5 buildtools_1.0.0
#> [31] abind_1.4-8 rmarkdown_2.32 tools_4.6.2
#> [34] htmltools_0.5.9