Filtering Taxa
After assigning common names, the next step is to remove taxa that should not be included in downstream analysis — synthetic control ASVs, non-food taxa (unassigned, and, for 12SV5, human reads), and any cohort-specific taxa that need to be excluded. These are listed out as independent steps below, rather than wrapped in a single function, so you can adapt, reorder, or skip individual steps as your study needs.
Removing Controls
If your sequencing run included a synthetic positive control (e.g. a synthetic trnL ASV), remove it by its exact species name:
Adjust the species name to match whatever your own control ASV is named if it differs from the default above.
Removing Non-Food Taxa
An unassigned trnL ASV has NA at every taxonomic rank, i.e. at superkingdom:
Removing Controls
Adjust the species name to match whatever your own control ASV is named if it differs from the default above.
Computing lowest_level
The next step, and agglomerating taxa afterward, both rely on a lowest_level column — the most specific non-NA taxonomic rank assigned to each ASV. Compute it once here with lowest_level() from foodseq.tools:
# install.packages("devtools")
devtools::install_github("LAD-LAB/foodseq.tools")
library(foodseq.tools)
tax_table(ps.12S) <- tax_table(ps.12S) %>%
data.frame() %>%
lowest_level() %>%
tax_table()
Removing Non-Food Taxa
Two things count as non-food for 12SV5: unassigned ASVs (NA at kingdom, or NA at both order and family) and human reads, which are commonly detected in 12SV5 sequencing of stool samples and reflect the host rather than dietary intake:
ps.12S <- subset_taxa(ps.12S, !(is.na(kingdom) | (is.na(family) & is.na(order))))
ps.12S <- subset_taxa(ps.12S, is.na(lowest_level) | lowest_level != "Homo sapiens")
Manual Review for Ambiguous Human-Matching ASVs
The lowest_level != "Homo sapiens" step above only catches ASVs the classifier itself assigned to human. Some ASVs may BLAST to human without being classified that way — for example, ASVs ambiguous between human and a closely related species. If you've identified such ASVs manually (e.g., through the BLAST review process), remove them by sequence:
Filtering unassigned taxa
It is recommended to filter out NAs at the highest level (i.e., superkingdom) for trnL and at Order + Family for 12SV5. This is because assignment_trnL() uses exact sequence matching, so any non-NA assignment reflects a true match in the reference and NAs appear only when no match exists. 12SV5, by contrast, is assigned by assignment_12S(), which uses a naive Bayesian classifier and makes assignments at every level along with bootstrap confidence values, which tend to fall off below Order. Any ASV that is NA at both the Order and Family level should be filtered out. Include Family in your filtering criteria to ensure you retain entries that do not have Order or Family assignments but still contain valid assignments at lower taxonomic ranks (e.g., due to gaps in the reference).
Cohort-Specific Removals
Some studies may require removing additional taxa based on the study design, after the steps above. Common examples include:
- Environmental contamination — for trnL, taxa like grasses or trees that reflect environmental DNA rather than dietary intake.
- Known contaminants — taxa identified during quality control as likely cross-contamination from positive controls or other samples.
- Study-specific exclusions — taxa that are not relevant to the research question (e.g., removing non-mammalian vertebrates from a study focused on meat consumption).
These removals are study-dependent and should be documented in your analysis scripts. Use subset_taxa() to filter by any column in the taxonomy table: