Matches a vector of taxonomic names against locally stored Darwin Core backbone databases. Returns a data.frame with one row per input name containing the matched name, accepted name, taxonomic hierarchy, and match quality information.
Usage
taxify(
x,
backbone = NULL,
fuzzy = TRUE,
fuzzy_threshold = 0.2,
fuzzy_method = c("dl", "levenshtein", "jw"),
aggregates = c("preserve", "collapse"),
region = NULL,
coords = NULL,
range = c("present", "native", "introduced"),
kingdom = NULL,
mode = c("fallback", "wide", "agreement"),
verbose = TRUE
)Arguments
- x
Character vector of taxonomic names.
- backbone
Character vector of backbone names (e.g.,
"wfo","col","gbif") or a singletaxify_backendobject. Several are tried in order as a fallback chain.NULL(default) uses every installed backbone in priority order, installing the default set (COL, GBIF, ITIS) on first use; override the priority withoptions(taxify.backbone_priority = ...)and the first-run set withoptions(taxify.default_backbones = ...).- fuzzy
Logical. Enable fuzzy matching for names that fail exact match. Default
TRUE.- fuzzy_threshold
Numeric. Maximum allowed distance for fuzzy matches. Two modes depending on the value:
Fractional (
0 < fuzzy_threshold < 1): normalized distance (edits / max name length). Default0.2is about 1 edit per 5 characters.Integer (
fuzzy_threshold >= 1): maximum raw edit count, e.g.fuzzy_threshold = 2Lallows at most 2 insertions/deletions/substitutions regardless of name length. Not supported forfuzzy_method = "jw".
- fuzzy_method
Character. One of
"dl"(Damerau-Levenshtein, default),"levenshtein", or"jw"(Jaro-Winkler).- aggregates
Character. How to treat species aggregates (names with an
agg./s.l.qualifier)."preserve"(default) keeps the aggregate as its own concept: it matches the backbone's aggregate taxon ("<binomial> aggr.") where one exists, otherwise falls back to the binomial. The output'saggregate_fallbackcolumn records which happened for each aggregate:TRUEwhere it fell back to the binomial,FALSEwhere it resolved to the dedicated aggregate taxon. Only Euro+Med and WoRMS carry aggregate taxa, so preserve falls back for the other backbones."collapse"strips the marker and matches the binomial species, the way any non-aggregate name is matched. Either way the qualifier is recorded in thequalifiercolumn.- region
Region(s) to constrain fuzzy matching to, or
NULL(default) for no geographic constraint. Botanical (WCVP, vascular plants): TDWG Level 3 codes ("BGM",c("BGM", "GER")) or region names at any level, matched case- and accent-insensitively against the bundled WGSRPD crosswalk – a Level 3 name ("Belgium"), a Level 2 region ("Middle Europe"), or a Level 1 continent ("Europe", which expands to all its codes). Marine (only when themarine_distributionasset is installed): a MEOW ecoregionECO_CODE, or an ecoregion / province / realm name (a province or realm expands to its member ecoregions). Seetaxify_regions()for both lists. When set, fuzzy candidates are restricted to species with range records in the region(s); exact matches are always kept. The filter only narrows genuinely ambiguous fuzzy candidates: a candidate is dropped only when the same input name has another candidate that is in-region or has no range data, so a match in a group with no range coverage is never affected and a name whose only candidate is out-of-region is still returned.- coords
Coordinates to constrain fuzzy matching to, mapped to region codes by point-in-polygon and unioned with
region. Points are tested against the WGSRPD botanical boundaries (yielding TDWG codes) and, when the marine asset is installed, the MEOW ecoregion boundaries (yieldingECO_CODEs), so a coastal point can resolve to both. A singlec(lon, lat)pair, a matrix/data.frame of longitude/latitude columns (namedlon/latorx/y, else the first two columns as lon, lat), or a point-geometry spatial object (an sf/sfcobject or a terraSpatVector, reprojected to longitude/latitude automatically).NULL(default) for none. Each boundary file is downloaded once and cached; coordinate lookup needs that download (or a prior cache). The point-in- polygon test uses terra or sf when installed, otherwise a native fallback; force the engine withoptions(taxify.pip_engine = "terra" | "sf" | "native").- range
Character. Which range statuses count as in-region when
regionorcoordsis set."present"(default) accepts any record (native, introduced, extinct, or unknown status) – the right choice for name disambiguation."native"accepts only native records,"introduced"only introduced (alien) records; both fold an ecological filter into matching and are for callers who want that. Ignored when no region is set.- kingdom
Character. Restrict matches to one or more kingdoms, to disambiguate a name shared across kingdoms (a Prunella that is both a bird and a plant, an Oenanthe that is both).
NULL(default) applies no constraint. Accepts a kingdom name or a common alias, case-insensitively:"animals"/"Animalia"/"Metazoa","plants"/"Plantae","fungi","bacteria","archaea","chromista","protozoa","viruses". A matched taxon is kept only when its kingdom is the requested one (or is unknown, which is never rejected); with the default multi-backbone fallback, a name a backbone resolves into the wrong kingdom is passed on to the next backbone, so the in-kingdom treatment wins. The kingdom is read from the backbone where it stores one (COL, ITIS, NCBI, OTT, WoRMS); for a backbone that does not (WFO, GBIF), it falls back to the genus register's kingdom, which cannot split a genus that is itself homonymous across kingdoms – name a kingdom-appropriatebackbonefor those.- mode
Character. How to combine results when
backbonenames more than one backbone."fallback"(default) is the fallback chain described above: one answer per name, from the first backbone that matched."wide"and"agreement"instead consult every backbone for every name and report how they compare, so a backbone disagreement (see the Backbone-specific accepted names section) is visible in one call rather than by querying each backbone by hand. Both return a strict superset of the"fallback"result (the same standard columns, withaccepted_namestill the fallback pick, so the frame still pipes into theadd_*()enrichments) plus:"wide": oneaccepted_<backbone>column per backbone and a logicalall_agree."agreement":n_backbones_matched,n_distinct_accepted, andall_agree.
all_agreeisTRUE/FALSEwhen at least two backbones matched the name andNAwhen fewer than two did (nothing to compare). Ignored (with a message) when only one backbone is given, since there is nothing to compare.- verbose
Logical. Print progress messages. Default
TRUE.
Value
A data.frame with one row per input name and the following columns:
- input_name
The original name as provided.
- matched_name
Full name in the backbone that matched. For an unresolved hybrid formula (
match_type = "hybrid_formula") it holds the input-parent cross (e.g."Salix alba x Salix fragilis") when both parents resolve, elseNA.- accepted_name
Resolved accepted name (equals
matched_nameif not a synonym). For a hybrid formula it holds the accepted-parent cross (both parents resolved), elseNA.- taxon_id
Backend-specific ID of the matched name.
- accepted_id
ID of the accepted name.
- rank
Taxonomic rank (species, subspecies, genus, etc.).
- family
Family name.
- genus
Genus name.
- epithet
Specific epithet.
- authorship
Authorship of the matched name.
- accepted_authorship
Authorship of the accepted name. For a synonym this is the author of the resolved accepted name, not the synonym's own author, so
accepted_nameandaccepted_authorshiptogether form the accepted name's full citation.- is_synonym
Logical. Was the match a synonym?
- is_hybrid
Logical. Was a hybrid marker detected in the input?
- hybrid_type
"nothogenus"("x Cupressocyparis leylandii"),"nothospecies"("Quercus x hispanica"),"formula"("Salix alba x Salix fragilis"), orNAfor a non-hybrid. Nothogenus and nothospecies resolve to a single backbone taxon in the usual columns. A formula resolves that way only where the backbone stores the cross; otherwisematch_typeis"hybrid_formula", the ID, rank and classification columns areNA, andmatched_name/accepted_namename the cross by its parents when both parents resolve. The parent binomials, and their accepted names, are added on demand byadd_hybrid_info().- qualifier
Canonical taxonomic qualifier found in the input name (
"cf.","aff.","agg.","s.l.","s.str.","sp.", ...), orNA. Spelling variants are folded to one token ("aggr.","agg"and"sensu lato"all map to"agg."/"s.l.").- qualifier_position
"genus"when the qualifier leads the name and qualifies the whole name (e.g."Cf. Pinus sylvestris"),"species"when it qualifies the species (inlinecf.or trailingagg.),NAwhen there is no qualifier.- aggregate_fallback
Logical. For an aggregate query under
aggregates = "preserve":FALSEwhen it resolved to the backbone's dedicated aggregate taxon,TRUEwhen no such taxon existed and it fell back to the nominal binomial.NAfor non-aggregate queries and underaggregates = "collapse", where the collapse is explicit.- match_type
One of
"exact","exact_ci","fuzzy","abbrev"(an abbreviated genus such as"Q. robur"resolved via genus initial plus epithet),"hybrid_formula"(a two-parent cross the backbone does not store; the ID, rank and classification columns areNA,matched_name/accepted_namename the cross by its parents when both resolve, andadd_hybrid_info()materializes the parents into thehybrid_parent_*columns), or"none".- fuzzy_dist
Normalized string distance (0–1),
NAif exact.- is_ambiguous
Logical.
TRUEwhen the matched scientificName had multiple synonym rows pointing to different accepted taxa at the same priority tier (homonym ambiguity). Disambiguated vianomenclaturalStatus = "Valid"when that column is in the backbone; for irreducible ambiguity, the scalar columns hold one candidate.- ambiguous_targets
Character.
|-joined list of conflicting accepted taxon IDs whenis_ambiguous = TRUE;NAotherwise.- backbone
Which backbone was used (e.g.,
"wfo","col","gbif").- backbone_version
Backend name, version, and download date (e.g.,
"wfo:2024-12 (2026-04-01)"). Useful for reproducibility.- kingdom_group
Coarse kingdom-level group of the matched genus, from the bundled genus register (used for cross-kingdom disambiguation);
NAwhen the genus is not in the register.- taxon_group
Broad taxonomic group of the matched genus, from the genus register;
NAwhen unavailable.- life_form
Life-form classification of the matched genus, from the genus register's family-based lookup;
NAwhen unavailable.
Details
By default taxify() matches against every installed backbone, tried in
priority order as a fallback chain (the COL syntheses, then the domain
authorities, then the broad aggregators). The chain is staged by match
quality: every backbone
is asked for an exact match first, and only the names still unresolved go
round again for a fuzzy one. A name is therefore resolved by the
highest-priority backbone that matches it at the best quality any backbone
reaches, so a near neighbour in an early backbone does not settle a name a
later backbone holds exactly. Names matched earlier are not re-matched later.
On a fresh setup with nothing installed yet, the first call downloads a
default set (COL, GBIF, ITIS) once; pre-install a different set with
install_backbones(). Name a backbone (or several) explicitly to match only
against that one, or those in that order.
Backbone-specific accepted names
Each backbone is an independent taxonomy, and they can legitimately disagree
on which name is accepted and which is a synonym. taxify() returns the
matched backbone's own current treatment; it does not reconcile backbones
against each other by voting (a consensus would regress toward the most
conservative treatment across backbones that copy one another). With the
default multi-backbone fallback, accepted_name is the pick of the
highest-priority backbone that matched at the best quality reached. To see
where backbones disagree, pass
mode = "wide" (or "agreement") for each backbone's accepted_name side by
side; to follow one authority, name a single backbone.
For example, the red and parma kangaroos: the GBIF Backbone Taxonomy
accepts Macropus rufus and Macropus parma, treating Osphranter rufus
and Notamacropus parma as synonyms of them, so
taxify("Osphranter rufus", backbone = "gbif") resolves to Macropus rufus.
The Catalogue of Life splits the genus and does the reverse, so
taxify("Macropus rufus", backbone = "col") resolves to Osphranter rufus.
Both are faithful to their source; the difference is in the backbones, not in
the matching.
Examples
# Runs offline against the bundled example database.
old <- options(taxify.data_dir = taxify_example_data())
# Match a few names
taxify(c("Quercus robur", "Pinus sylvestris"))
# Disable fuzzy matching
taxify("Quercus robus", fuzzy = FALSE)
# Constrain fuzzy candidates to a geographic region: a TDWG Level 3 code,
# or a region name resolved via the bundled WGSRPD crosswalk
taxify("Quercus robus", region = "EUR")
taxify("Quercus robus", region = "Belgium")
# Constrain by coordinates (downloads WGSRPD boundaries on first use)
if (FALSE) { # \dontrun{
taxify("Quercus robus", coords = c(4.35, 50.85))
} # }
# Fallback chain: try WFO first, then COL for unmatched
taxify(c("Quercus robur", "Panthera leo"),
backbone = c("wfo", "col"))
# Compare how two backbones resolve the same names, side by side
taxify(c("Quercus robur", "Pinus sylvestris"),
backbone = c("wfo", "col"), mode = "wide")
options(old)