This vignette maps the name-resolution calls of taxize, WorldFlora,
lcvplants, rWCVP, taxadb and Taxonstand to their taxify equivalents,
then runs the same tasks side by side in the old package and in taxify.
The R tools for taxonomic name resolution differ in where the data lives
(local files or remote APIs), how many backbones they cover, and what
they return. taxify matches against
19
backbones offline and can chain them in a single call:
taxify(names, backbone = c("col", "gbif", "itis")). The
matching engine is written in C with genus-blocked fuzzy joins, and ten
thousand names resolve in seconds. Results pipe directly into more than
eighty published trait and status datasets (IUCN, GRIIS, WCVP, EIVE,
EltonTraits, etc.) with a single |> chain. Backbones are
versioned files on disk, and the backbone_version column
records exactly which snapshot was used. If your workflow already uses
one of the other packages and you are happy with it, there is no urgent
reason to switch.
- Map each call of the old package to its taxify equivalent with the tables below.
-
Resolve the names with
taxify(), naming thebackbonethe old package read. -
Chain backbones by passing a vector to
backbone; unmatched names cascade to the next one. -
Enrich the result with the
add_*()layers thatlist_enrichments()lists, or join your own table withadd_data().
Example
The packages compared
The table summarizes the packages most likely to overlap with a taxify workflow.
| Package | Source data | Coverage | Access | Closest taxify analogue |
|---|---|---|---|---|
| taxize | ~20 web services (NCBI, ITIS, GBIF, EOL, IUCN, WoRMS, Tropicos, …) | All kingdoms | Live API |
taxify(backbone = c(...)) with the relevant local
backbone(s) |
| WorldFlora | World Flora Online classification (WFO.match) |
Land plants (vascular + bryophytes) | Local file | taxify(backbone = "wfo") |
| lcvplants | Leipzig Catalogue of Vascular Plants | Vascular plants | Bundled in package | taxify(backbone = "lcvp") |
| rWCVP | World Checklist of Vascular Plants (Kew) | Vascular plants | Local snapshot |
taxify(backbone = "wcvp") for names;
add_wcvp() for native ranges |
| taxadb | GBIF, ITIS, COL, NCBI, OTT, WFO snapshots | All kingdoms | Local DuckDB / MonetDB | taxify(backbone = c(...)) |
| Taxonstand | The Plant List (retired by Kew in 2013, superseded by WCVP and WFO) | Vascular plants | Bundled in package | taxify(backbone = "wfo") |
| U.Taxonstand | User-supplied or bundled checklists | Configurable | Local |
taxify(backbone = ...) plus
add_data()
|
| bdc | taxadb + GNR for the taxonomic step inside a larger biodiversity-cleaning workflow | All kingdoms | Local + API |
taxify() for the matching step |
| TNRS | TNRS web service (BIEN / iDigBio) | Plants | Live API |
taxify(backbone = "wfo") or similar |
| rgbif, worrms, ritis | GBIF / WoRMS / ITIS web APIs | One backbone each | Live API | taxify(backbone = "gbif" / "worms" / "itis") |
From taxize
The taxize name-resolution functions and their closest taxify equivalents:
| taxize function | taxify equivalent | Notes |
|---|---|---|
gnr_resolve() |
taxify() |
Any backbone; returns best match per name |
classification() |
taxify() + add_classification()
|
family, genus, rank in the
core output; add_classification() fills kingdom / phylum /
class / order |
synonyms() |
synonyms() |
Lists every synonym that resolves to a name’s accepted taxon |
children() |
children() |
Lists the accepted taxa within a genus or family |
downstream() |
downstream() |
Every accepted taxon at a target rank beneath a higher taxon (species by default) |
upstream() |
upstream() |
The ancestors of a taxon, one row per rank |
tax_name() |
taxify() |
family, genus, rank
columns |
sci2comm() |
sci2comm() or add_common_names()
|
GBIF, NCBI and Open Tree vernacular names;
add_common_names() is the pipe enrichment, by language |
comm2sci() |
comm2sci() |
Common name to accepted scientific name(s), read from the same vernacular tables |
id2name() |
id2name() |
Backbone ID (GBIF key, TSN, AphiaID) to name, rank and accepted name |
class2tree() |
class2tree() |
Taxonomy tree from the classification, as Newick |
lowest_common() |
lowest_common() |
Deepest rank a set of names shares |
Database IDs come back in the taxon_id and
accepted_id columns of every taxify() result,
so the get_*id() family has no separate call. taxize also
retrieves occurrence and sequence data; those tasks are outside taxify’s
scope, and When another
package fits better points to the packages for them.
taxize returned results in varied formats depending on the function
(classification() gave a nested list of data.frames,
synonyms() another nested list, get_tsn() a
character vector with attributes). taxify returns the same 27-column
data.frame from every taxify() call, with synonym status,
classification, and match quality as columns.
From WorldFlora
| WorldFlora function | taxify equivalent | Notes |
|---|---|---|
WFO.match() |
taxify(backbone = "wfo") |
Both do exact + fuzzy in one call. WFO.match() returns
several candidate rows per input name |
WFO.one() |
taxify() |
The selection step. WFO.one() collapses
WFO.match()’s candidate rows to one best match per input;
taxify() returns one best-match row directly, so the two
steps are one call |
WFO.match.fuzzyjoin() |
taxify(backbone = "wfo") |
Same matching as WFO.match(), faster
fuzzyjoin-based engine; taxify is fast by default, so there
is no separate call |
WFO.synonyms(accepted) |
synonyms(x, backbone = "wfo") |
Expands a name to the synonyms of its accepted taxon (one-to-many).
The forward direction, synonym to accepted, is in the
taxify() output (is_synonym,
accepted_name, accepted_id) |
WorldFlora returns a wide data.frame with WFO-specific column names
(scientificName, taxonID,
taxonomicStatus, acceptedNameUsageID, plus
authorship and bibliographic fields). taxify normalizes these into a
backbone-agnostic schema: matched_name,
taxon_id, accepted_name,
accepted_id, and so on. The WFO-specific columns are still
accessible via add_wfo_info(), and the default output has
the same 27 columns whether the backbone is WFO, COL, or GBIF.
taxify also manages the backbone: the first taxify()
call downloads it, subsequent calls reuse the local copy, and a
once-per-session version check keeps it current.
From lcvplants
lcvplants
wraps the Leipzig Catalogue of Vascular Plants and ships the LCVP table
as bundled data. The package centres on LCVP() and
lcvp_search().
| lcvplants function | taxify equivalent | Notes |
|---|---|---|
LCVP(splist) |
taxify(splist, backbone = "lcvp") |
Returns the standardized 27-column data.frame |
lcvp_search() |
taxify() |
Search by name; same output schema |
lcvp_fuzzy_search() |
taxify(fuzzy = TRUE) |
Genus-blocked Damerau-Levenshtein; on by default |
tab_lcvp (data object) |
taxify_data_dir() / lcvp / latest / lcvp.vtr |
The LCVP snapshot is shipped as a .vtr file instead of
an in-package data object |
The LCVP and WCVP backbones can be combined in a single fallback chain to arbitrate between the Leipzig and Kew vascular-plant authorities:
From rWCVP
rWCVP is the Kew
package for the World Checklist of Vascular Plants. Its name-resolution
side centres on wcvp_match_names() and
wcvp_check_gbif(); its distribution-query side has no
taxify replacement.
| rWCVP function | taxify equivalent | Notes |
|---|---|---|
wcvp_match_names() |
taxify(backbone = "wcvp") |
Exact + fuzzy in one call |
wcvp_check_gbif() |
taxify(backbone = c("wcvp", "gbif")) |
Cascade WCVP first, GBIF as fallback |
wcvp_distribution() |
add_wcvp() |
Native range by TDWG region (the add_wcvp()
enrichment) |
wcvp_synonyms() |
taxify(), synonyms(backbone = "wcvp")
|
is_synonym and accepted_name columns in
the taxify() output; synonyms() lists the
synonyms of a taxon |
get_wcvp() |
automatic | The backbone downloads on first
taxify(backbone = "wcvp") call |
rWCVP’s distribution-query functions (wcvp_occ_mat(),
generate_checklist()) operate on TDWG geography and are
outside taxify’s scope. For native-range data joined to a name-resolved
result, add_wcvp() covers the most common case; for full
geographic queries, rWCVP remains the right tool.
From taxadb
taxadb is the closest functional analogue to taxify. Both store backbone snapshots locally and avoid network calls at query time. taxadb returns a long-format table for exact-key joins, while taxify returns a flat one-row-per-input result with fuzzy matching, synonym resolution, and trait enrichment built in.
| taxadb function | taxify equivalent | Notes |
|---|---|---|
td_create("itis") |
automatic | First taxify(backbone = "itis") call downloads the
.vtr snapshot |
filter_name(names, "itis") |
taxify(names, backbone = "itis") |
Exact match against the local snapshot |
filter_id(ids, "itis") |
id2name(ids, backbone = "itis") |
Name, rank, classification and accepted name for each ID |
synonyms(names, "itis") |
taxify() |
is_synonym, accepted_name,
accepted_id in the output |
clean_names() |
automatic |
taxify() runs the cleaning pipeline (authorship,
qualifiers, hybrid markers, orthography) before matching |
| (no fuzzy match) | taxify(fuzzy = TRUE) |
Genus-blocked Damerau-Levenshtein, on by default |
The two largest practical differences are matching scope and output
shape. taxadb is built around exact lookups against pre-cleaned input;
taxify cleans the input and runs fuzzy matching on names that do not
match exactly, which catches typos, orthographic variants, and
authorship strings without a separate preprocessing step. taxadb returns
multiple rows per input when a name has multiple matches, and you pick
the row you want with dplyr::filter. taxify returns one row
per input with a best-match selection rule (ACCEPTED over SYNONYM,
species rank over higher ranks, lowest ID as tiebreaker), and reports
the match type and fuzzy distance as columns.
From Taxonstand
Taxonstand was built around The Plant List, which Kew retired in 2013 in favour of WCVP and WFO. The package still works, but the underlying taxonomy has not been updated since the retirement.
| Taxonstand function | taxify equivalent | Notes |
|---|---|---|
TPL(splist) |
taxify(splist, backbone = c("wcvp", "wfo")) |
Replace TPL with its successors |
TPLck() |
taxify() |
Single-name check; same output schema |
The simplest migration replaces backbone = "tpl" with
backbone = c("wcvp", "wfo"), or with
backbone = c("lcvp", "wcvp", "wfo") for triple arbitration
across the three large vascular-plant authorities.
Basic name resolution
With taxize, name resolution typically meant several separate calls:
gnr_resolve() for matching, get_gbifid() for
IDs, classification() for hierarchy,
synonyms() for synonym status.
# --- taxize ---
library(taxize)
names <- c("Quercus robur", "Pinus sylvestris", "Betula pendula",
"Panthera leo", "Salmo trutta")
resolved <- gnr_resolve(names, best_match_only = TRUE)
gbif_ids <- get_gbifid(names)
class_list <- classification(gbif_ids, db = "gbif")
syn_list <- synonyms(gbif_ids, db = "gbif")With taxify, all of that is one call, returning a data.frame with 27 columns and one row per input name:
WFO matching with fuzzy matching and synonyms
With WorldFlora, the typical workflow loads the backbone, runs the
match (exact and fuzzy together, here with the faster
fuzzyjoin engine), then collapses the candidate rows to one
best match per input.
# --- WorldFlora ---
library(WorldFlora)
wfo_data <- read.delim("classification.txt")
names <- c("Quercus robur", "Quercus pedonculata",
"Pinus silvestris", "Rosa canina")
matched <- WFO.match.fuzzyjoin(names, WFO.data = wfo_data)
best <- WFO.one(matched)In taxify, exact matching, fuzzy matching, and synonym resolution happen in a single call:
# --- taxify ---
names <- c("Quercus robur", "Quercus pedonculata",
"Pinus silvestris", "Rosa canina")
result <- taxify(names, backbone = "wfo")
# Misspellings are caught by fuzzy matching:
result[, c("input_name", "matched_name", "match_type", "fuzzy_dist")]
# input_name matched_name match_type fuzzy_dist
# 1 Quercus robur Quercus robur exact NA
# 2 Quercus pedonculata Quercus pedunculata fuzzy 0.053
# 3 Pinus silvestris Pinus sylvestris fuzzy 0.063
# 4 Rosa canina Rosa canina exact NA
# Synonyms resolved automatically:
result[, c("input_name", "is_synonym", "accepted_name")]Quercus pedonculata is both a misspelling and a synonym.
The fuzzy matcher corrects the spelling to
Quercus pedunculata, and the synonym resolver maps it to
Quercus robur.
Multi-backbone fallback with enrichments
A vector of backbones forms a fallback chain: names left unmatched by one backbone cascade to the next.
# Mixed kingdom input: plants, animals, fungi
names <- c(
"Quercus robur", # plant (matched by WFO)
"Panthera leo", # animal (not in WFO, picked up by GBIF)
"Amanita muscaria", # fungus (not in WFO, picked up by GBIF)
"Salmo trutta", # fish (not in WFO, picked up by GBIF)
"Arabidopsis thaliana" # plant (in both WFO and GBIF)
)
# WFO first (best for plants), GBIF as fallback (all kingdoms)
result <- taxify(names, backbone = c("wfo", "gbif"))
# The backbone column shows which database matched each name:
result[, c("input_name", "backbone", "family")]
# input_name backbone family
# 1 Quercus robur wfo Fagaceae
# 2 Panthera leo gbif Felidae
# 3 Amanita muscaria gbif Amanitaceae
# 4 Salmo trutta gbif Salmonidae
# 5 Arabidopsis thaliana wfo Brassicaceae
# Enrich with traits:
result |>
add_iucn() |>
add_zanne()
# Or join custom data:
my_traits <- data.frame(
species = c("Quercus robur", "Panthera leo"),
max_height_m = c(35, NA),
body_mass_kg = c(NA, 190)
)
result |> add_data(my_traits, species_col = "species")Discovering enrichments
The enrichment datasets cover conservation status, invasive species,
functional traits, morphological measurements, and vernacular names, and
join to the result through the add_*() functions.
list_enrichments() lists every source-named
add_*() door with its metadata:
Each enrichment downloads on first use and is cached locally,
following the same pattern as backbones. The cross-source
add_trait() verb gathers a single trait across every source
that carries it.
Key differences at a glance
Offline matching. taxify downloads backbone files once and matches locally. After the initial download (typically 50–300 MB depending on the backbone), no internet connection is needed.
Multi-backbone. taxify supports 19 backbones through a single function, with optional fallback chains that cascade unmatched names.
Output format. taxify() returns a
data.frame with 27 standardized columns, regardless of the backbone:
| Column | Type | Content |
|---|---|---|
input_name |
character | Original name as submitted |
matched_name |
character | Closest match in the backbone |
accepted_name |
character | Accepted name after synonym resolution |
taxon_id |
character | Backend-specific ID of the matched name |
accepted_id |
character | ID of the accepted name |
rank |
character | Taxonomic rank (species, genus, family, etc.) |
family |
character | Family name |
genus |
character | Genus name |
epithet |
character | Specific epithet |
authorship |
character | Taxonomic authority |
accepted_authorship |
character | Authorship of the accepted name |
is_synonym |
logical | Was the matched name a synonym? |
taxonomic_status |
character | The matched record’s status as the backbone writes it
("ACCEPTED", "SYNONYM", WFO’s
"UNCHECKED", …) |
is_hybrid |
logical | Hybrid marker detected in the input? |
match_type |
character |
"exact", "exact_ci",
"abbrev", "fuzzy",
"hybrid_formula", "rank_fallback",
"basionym", or "none"
|
fuzzy_dist |
numeric | Normalized edit distance (NA if exact) |
n_ids |
integer | Distinct accepted taxa the backbone files the name under |
accepted_ids |
character | All of those accepted IDs, pipe-separated, the pick first |
backbone |
character | Which backbone matched this name |
backbone_version |
character | Backend name, version, and download date |
kingdom_group |
character | Coarse kingdom group (from the genus register) |
taxon_group |
character | Taxon grouping (from the genus register) |
life_form |
character | Life form (from the genus register) |
qualifier |
character | Canonical taxonomic qualifier (cf., aff., agg., s.l., …) |
qualifier_position |
character |
"genus" or "species" placement of the
qualifier |
aggregate_fallback |
logical | TRUE when an aggregate query fell back to the binomial |
hybrid_type |
character | Hybrid formula / type detected |
Speed. taxify uses vectra’s C-level join engine with hash indexes and genus-blocked fuzzy joins, processing thousands of names per second.
Reproducibility. taxify pins backbone versions
locally and records the version string in the
backbone_version column of every result. The same backbone
file produces the same output indefinitely. Version pinning is also
available: taxify_download("col", version = "2024.06")
downloads a specific release.
When another package fits better
taxify resolves scientific names to accepted names, returns classification metadata, and joins enrichment layers. The related packages remain the right answer in these situations:
Distribution and range queries. rWCVP exposes WCVP’s TDWG-region geography directly through
wcvp_distribution(),wcvp_occ_mat(), andgenerate_checklist(). taxify covers the most common native-range join throughadd_wcvp(); full geographic queries belong in rWCVP.Live API access to upstream databases. taxize, rgbif, worrms, ritis, and TNRS query their backbones in real time and return the latest annotation for a taxon immediately. taxify queries local files: if a name was added to a backbone yesterday and taxify’s local copy is from last month, taxify will not find it until the backbone is updated. For workflows where freshness matters more than reproducibility, a direct API client (rgbif, worrms, ritis) may be the better fit. The same applies to common names:
comm2sci()reads the bundled GBIF, NCBI and Open Tree vernacular tables, whilergbif::name_suggest()accepts common names against the live GBIF API.Tree-based and phylogenetic queries.
downstream()andchildren()list descendants from the backbone’s classification, andclass2tree()builds a taxonomy tree from it. For the Open Tree of Life synthetic tree, use rotl (rotl::tol_subtree()); rgbif’sname_usage(key, data = "children")lists the children of a GBIF usage key live. For phylogenetic data, use rotl or phylomatic.Occurrence data. rgbif and spocc are the standard tools.
Sequence data. The rentrez package handles GenBank/NCBI queries directly.
Wider biodiversity-data cleaning. bdc wraps the entire data-cleaning workflow (coordinate cleaning, dataset merging, taxonomic harmonization, occurrence flagging). taxify can replace its taxonomic step alone if you prefer offline backbones over taxadb + GNR; the rest of bdc’s pipeline is outside taxify’s scope.
Interactive, per-name resolution with manual disambiguation. taxize had interactive modes where the user could pick among multiple candidates. taxify picks the best match automatically (on GBIF a key with occurrence records over one without, then accepted name over synonym, species rank over higher ranks, lowest ID as tiebreaker), records every accepted ID of the name in
accepted_ids, and lists them withtaxify_ids(). If per-name interactive choice is needed, direct API calls may be preferable.Column-oriented querying of a backbone. taxadb stores backbones in DuckDB / MonetDB and exposes them through dplyr verbs, a natural fit when the analysis is itself a SQL-style transformation of the backbone. taxify exposes the underlying
.vtrfiles through vectra for this kind of work, but taxadb’s dplyr surface is more ergonomic for custom queries. For workflows that need a single resolved name per input plus enrichment joins, taxify’s flat output is closer to the goal.