Comparison of DADA2 taxonomy and phylogenetic placement

Author

matricaria.suaveolens@gmail.com

Published

June 2, 2026

Code
TAXDB <- 'sbdi-gtdb_R22-RS232-1'
GTDB_TAXRANKS    <- c('domain', 'phylum', 'class', 'order', 'family', 'genus', 'species')
ORDERED_TAXRANKS <- c('domain', 'kingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species', 'strain', 'subspecies')
BLAST6_COLNAMES  <- c('qseqid', 'sseqid', 'pident', 'length', 'mismatch', 'gapopen', 'qstart', 'qend', 'sstart', 'send', 'evalue', 'bitscore')
BLAST6_COLTYPES  <- 'ccdiiiiiiidd'
Code
rank <- function(ds) {
  ds %>%
    mutate(
      rank = case_when(
        !is.na(species) ~ 'species',
        !is.na(genus)   ~ 'genus',
        !is.na(family)  ~ 'family',
        !is.na(order)   ~ 'order',
        !is.na(class)   ~ 'class',
        !is.na(phylum)  ~ 'phylum',
        !is.na(domain)  ~ 'domain'
      )
    )
}
Code
taxonomy <- read_tsv(
  'data/lmo16s.sbdi-gtdb.taxonomy.tsv',
  col_types = cols(.default = col_character(), confidence = col_double())
) %>%
  anti_join(
    read_tsv(
      'data/lmo16s.silva.taxonomy.tsv',
      col_types = cols(.default = col_character(), confidence = col_double())
    ) %>%
      filter(Class == 'Chloroplast'),
    by = join_by(ASV_ID)
  ) %>%
  rename_with(str_to_lower) %>%
  rank()

samples <- read_sheet('https://docs.google.com/spreadsheets/d/1Pxw-pXlSCCEORKOEwm9GrDxHVLca_ipwgpDdpphgARA/edit?gid=288998864#gid=288998864') %>%
  filter(project == 'LMO', ! replaced) %>%
  mutate(
    filter_fraction = as.character(filter_fraction),
    replicate       = as.character(replicate)
  ) %>%
  unnest(date)

counts <- read_tsv('data/lmo16s.tsv.gz', col_types = 'cci') %>%
  semi_join(taxonomy, by = join_by(asv_id)) %>%
  group_by(sample) %>%
  mutate(relab = count/sum(count)) %>%
  ungroup()

pplace <- read_tsv(Sys.glob('data/lmo16s.*.sbdi-gtdb.pplace.tsv'), col_types = 'cddddc') %>%
  rename_with(str_to_lower) %>%
  rename(asv_id = name) %>%
  mutate(taxopath = str_remove_all(taxopath, '[a-z]__')) %>%
  separate(taxopath, into = GTDB_TAXRANKS, sep = ';', fill = 'right') %>%
  semi_join(taxonomy, by = join_by(asv_id)) %>%
  rank()

Version history

  • 20260602
    • Assignment specificity comparison

Summary

I compared the DADA2 method assignTaxonomy with phylogenetic placement performed by nf-core/phyloplace using the same GTDB-SBDI database and the full set of LMO 16S ASV sequences. The latter turned out to assign substantially more ASVs at the more specific ranks species and genus. At the level of individual ASVs, I could observe movements between ranks in both directions in terms of specificity, i.e. from more to less specific in the DADA2 assignment and phylogenetic placement respectively. The addSpecies method of DADA2, based on exact matches to reference sequences, assigned a very small proportion of ASVs to species. Overall, phylogenetic placement appears to outperform the sequence composition-based DADA2 algorithm.

Introduction

Materials and Methods

I assigned taxonomy to the ASVs from the LMO time series using the SBDI-GTDB database (release R11-RS232; Lundin and Andersson (2021)) using the standard DADA2 method assignTaxonomy (Callahan et al. (2016)) and phylogenetic placement with nf-core/phyloplace (Lundin (2025)), both called as part of nf-core/ampliseq (Straub et al. (2020)). After removal of ASVs assigned to the “Chloroplast” class by SILVA (Quast et al. (2013)), 199619 remained.

I also counted the number of ASVs assigned to species by DADA2’s addSpecies method that is based on exact matches to reference sequences with unambiguous species assignment.

R and packages

This analysis was run with R version 4.6.0 (2026-04-24). Versions of packages used can be found in Table 1.

Code
cite_packages(output = "table", pkgs = "Session", out.dir = getwd()) %>%
  kable()
Table 1: Versions of R and packages used in this analysis.
Package Version Citation
base 4.6.0 R Core Team (2026)
DT 0.34.0 Xie et al. (2025)
ggsankey 0.0.99999 Sjoberg (2026)
kfigr 1.2.1 Koohafkan (2021)
knitr 1.51 Xie (2014); Xie (2015); Xie (2025)
patchwork 1.3.2 Pedersen (2025)
tidyverse 2.0.0 Wickham et al. (2019)

Results

DADA2 assigned 198879 ASVs at least at the domain level, while nf-core/phyloplace placed 199234. (The alternative addSpecies method of DADA2 assigned only 3279 ASVs to species based on exact matches to unambiguous reference sequences.) Phylogenetic placement proved to be substantially more specific than the DADA2 assignTaxonomy (Figure 1 A) with 111678 ASVs placed at species level with nf-core/phyloplace compared with only 75323 assigned to species by DADA2. Movement between ranks occurred both from and to more specific, with both algorithms (Figure 1 B). Placement species were recruited from all ranks in the assignTaxonomy, while species in the latter were mostly assigned either to species or genus in the former (with a few exceptions moving to order).

(Surprisingly few ASVs were placed at the family rank.)

Code
p0 <- taxonomy %>%
  filter(!is.na(rank)) %>%
  mutate(source = 'DADA2-assignTaxonomy') %>%
  count(source, rank) %>%
  union(
    pplace %>%
      semi_join(taxonomy, by = join_by(asv_id)) %>%
      mutate(source = 'nf-core/phyloplace') %>%
      count(source,rank)
  ) %>%
  mutate(rank = factor(rank, levels = GTDB_TAXRANKS, ordered = TRUE)) %>%
  ggplot(aes(x = rank, y = n, fill = source)) +
  geom_col(position = 'dodge') +
  geom_label(aes(y = n + 1e4, label = n)) +
  labs(x = '', y = '', fill = '')
p1 <- taxonomy %>% transmute(asv_id, DADA2 = rank) %>%
  full_join(
    pplace %>% transmute(asv_id, phyloplace = rank),
    by = join_by(asv_id)
  ) %>%
  make_long(DADA2, phyloplace) %>%
  ggplot(aes(x = x, next_x = next_x, node = node, next_node = next_node, fill = factor(node, levels = GTDB_TAXRANKS, ordered = TRUE))) +
  geom_sankey(colour = 'black') +
  labs(x = '', y = '', fill = '') +
  scale_fill_brewer(palette = 'Paired')
p0 / p1 +
  plot_annotation(tag_levels = 'A') +
  plot_layout(heights = c(2, 3))
Figure 1: ASVs at different ranks. A) Number of ASVs assigned to the different ranks for each algorithm. B) Movement of ASVs between ranks in the two algorithms.

Discussion

References

Code
# vim: sw=2

References

Callahan, Benjamin J., Paul J. McMurdie, Michael J. Rosen, Andrew W. Han, Amy Jo A. Johnson, and Susan P. Holmes. 2016. “DADA2: High-Resolution Sample Inference from Illumina Amplicon Data.” Nature Methods 13 (7): 581–83. https://doi.org/10.1038/nmeth.3869.
Koohafkan, Michael C. 2021. kfigr: Integrated Code Chunk Anchoring and Referencing for r Markdown Documents. https://doi.org/10.32614/CRAN.package.kfigr.
Lundin, Daniel. 2025. Nf-Core/Phyloplace: Phylosearch Release. V. 2.0.0. Zenodo, released February. https://doi.org/10.5281/zenodo.14906186.
Lundin, Daniel, and Anders Andersson. 2021. SBDI Sativa Curated 16S GTDB Database. August. https://doi.org/10.17044/scilifelab.14869077.v11.
Pedersen, Thomas Lin. 2025. patchwork: The Composer of Plots. https://doi.org/10.32614/CRAN.package.patchwork.
Quast, Christian, Elmar Pruesse, Pelin Yilmaz, et al. 2013. “The SILVA Ribosomal RNA Gene Database Project: Improved Data Processing and Web-Based Tools.” Nucleic Acids Research 41 (D1): D590–96. https://doi.org/10.1093/nar/gks1219.
R Core Team. 2026. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing. https://doi.org/10.32614/R.manuals.
Sjoberg, David. 2026. ggsankey: Sankey, Alluvial and Sankey Bump Plots. https://github.com/davidsjoberg/ggsankey.
Straub, Daniel, Nia Blackwell, Adrian Langarica-Fuentes, Alexander Peltzer, Sven Nahnsen, and Sara Kleindienst. 2020. “Interpretations of Environmental Microbial Community Studies Are Biased by the Selected 16S rRNA (Gene) Amplicon Sequencing Pipeline.” Frontiers in Microbiology 11. https://doi.org/10.3389/fmicb.2020.550420.
Wickham, Hadley, Mara Averick, Jennifer Bryan, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
Xie, Yihui. 2014. “knitr: A Comprehensive Tool for Reproducible Research in R.” In Implementing Reproducible Computational Research, edited by Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman; Hall/CRC.
Xie, Yihui. 2015. Dynamic Documents with R and Knitr. 2nd ed. Chapman; Hall/CRC. https://yihui.org/knitr/.
Xie, Yihui. 2025. knitr: A General-Purpose Package for Dynamic Report Generation in R. https://yihui.org/knitr/.
Xie, Yihui, Joe Cheng, Xianying Tan, and Garrick Aden-Buie. 2025. DT: A Wrapper of the JavaScript Library “DataTables”. https://doi.org/10.32614/CRAN.package.DT.