This article shows how to attach
published trait, status and range data to matched names: one dataset
with its add_<source>() function, one trait from
every dataset that has it with add_trait(), and the
datasets that hold one value per country, region or language. It ends
with how the values are joined, where each one came from and how to cite
them. Installation is covered in Get started.
The source, size and licence of every dataset are listed in The backbones and datasets.
Find a dataset with
list_enrichments(), or a trait with
list_traits().
Attach one dataset with its
add_<source>() function.
Gather one trait from several datasets with
add_trait().
Check coverage and versions with
summary(), and cite the sources with
cite().
taxify can attach
109
published datasets. list_enrichments() lists them with
their version, number of rows and whether the dataset is a fixed
release:
datasets <- list_enrichments(verbose = FALSE)
head(datasets[, c("name", "version", "nrow", "static")])
#> name version nrow static
#> 1 iucn 2026.08 254965 FALSE
#> 2 griis 2026.08 437664 FALSE
#> 3 alien_first_records 2026.08 340104 TRUE
#> 4 wcvp 2026.08 4909534 FALSE
#> 5 eive 2026.08 44811 TRUE
#> 6 elton_traits 2026.08 29052 TRUEEach dataset has its own function, named after its source, and a help
page with its columns, licence and reference: ?add_zanne
for the woodiness compiled by Zanne et al. (2014),
?add_eive for the Ecological Indicator Values for Europe
(Dengler et al. 2023).
The examples use five plants matched against the Catalogue of Life (COL):
plants <- c(
"Quercus robur", "Fagus sylvatica", "Abies alba",
"Arrhenatherum elatius", "Plantago lanceolata"
)
res <- taxify(plants, backbone = "col", verbose = FALSE)add_zanne() adds the woodiness of each species:
wood <- add_zanne(res)
wood[, c("input_name", "woodiness")]
#> input_name woodiness
#> 1 Quercus robur woody
#> 2 Fagus sylvatica woody
#> 3 Abies alba woody
#> 4 Arrhenatherum elatius herbaceous
#> 5 Plantago lanceolata herbaceous
#> Sources: COL 2026.09, Zanne et al. 2014 2026.08 | cite() for full citationsenrichment_cols() lists all of a dataset’s columns, and
cols chooses: a vector of names, or "all":
enrichment_cols("zanne")
#> column type
#> 1 woodiness character
#> 2 woodiness_count numeric
wood_all <- add_zanne(res, cols = "all")
setdiff(names(wood_all), names(res))
#> [1] "woodiness" "woodiness_count"The functions return the result with the new columns on the right, so they can be chained:
both <- res |> add_zanne() |> add_eive()
both[, c("accepted_name", "woodiness", "eive_light", "eive_moisture")]
#> accepted_name woodiness eive_light eive_moisture
#> 1 Quercus robur woody 6.241077 4.802554
#> 2 Fagus sylvatica woody 3.003906 4.570789
#> 3 Abies alba woody 3.041214 5.183157
#> 4 Arrhenatherum elatius herbaceous 7.647964 4.343963
#> 5 Plantago lanceolata herbaceous 6.668470 4.094346
#> Sources: COL 2026.09, Zanne et al. 2014 2026.08, EIVE 1.0 2026.08 | cite() for full citationsSome datasets hold a value for each country, region or language.
Their function takes the place or language as an argument.
add_griis() reads the Global Register of Introduced and
Invasive Species (GRIIS) for countries given as two-letter ISO codes.
One code gives one column, invasive_status; several give a
column each, with the code as suffix:
aliens <- c(
"Robinia pseudoacacia", "Ailanthus altissima", "Impatiens glandulifera",
"Reynoutria japonica", "Quercus robur"
)
al <- taxify(aliens, backbone = "col", verbose = FALSE)
gr <- add_griis(al, country = c("AT", "DE", "GB"))
gr[, c("input_name", "invasive_status_AT", "invasive_status_DE",
"invasive_status_GB")]
#> input_name invasive_status_AT invasive_status_DE
#> 1 Robinia pseudoacacia invasive invasive
#> 2 Ailanthus altissima invasive invasive
#> 3 Impatiens glandulifera invasive introduced
#> 4 Reynoutria japonica invasive introduced
#> 5 Quercus robur <NA> <NA>
#> invasive_status_GB
#> 1 invasive
#> 2 invasive
#> 3 invasive
#> 4 invasive
#> 5 <NA>
#> Sources: COL 2026.09, GRIIS 2026.08 | cite() for full citationsQuercus robur is native in all three countries. GRIIS
focuses on introduced and invasive species, so it has no record for the
oak, and its rows are NA: an NA means that the
dataset has no record, not that the species is native.
enrichment_groups("griis") lists the codes, and
country = "all" takes every country.
taxify_long() turns the suffixed columns into rows, one
per species and country:
long <- taxify_long(gr)
head(long[, c("input_name", "country_code", "invasive_status")])
#> input_name country_code invasive_status
#> 1 Robinia pseudoacacia AT invasive
#> 2 Ailanthus altissima AT invasive
#> 3 Impatiens glandulifera AT invasive
#> 4 Reynoutria japonica AT invasive
#> 5 Quercus robur AT <NA>
#> 6 Robinia pseudoacacia DE invasive
#> Sources: COL 2026.09, GRIIS 2026.08 | cite() for full citationsadd_wcvp() works the same way for the botanical regions
of the World Checklist of Vascular Plants (WCVP), coded as in Matching within a region, and
add_common_names() for languages:
trees <- c("Quercus robur", "Nothofagus pumilio", "Sequoiadendron giganteum")
tr <- taxify(trees, backbone = "col", verbose = FALSE)
wc <- add_wcvp(tr, region = c("GER", "AGS"))
wc[, c("input_name", "native_status_GER", "native_status_AGS")]
#> input_name native_status_GER native_status_AGS
#> 1 Quercus robur native <NA>
#> 2 Nothofagus pumilio <NA> native
#> 3 Sequoiadendron giganteum introduced <NA>
#> Sources: COL 2026.09, WCVP (Kew) 2026.08 | cite() for full citationsNothofagus pumilio is native to southern Argentina
(AGS). The giant sequoia, native to California, is recorded
in Germany as introduced.
add_common_names() takes a language code and adds one
name per species in that language:
cn <- add_common_names(res, lang = "de")
cn[, c("input_name", "common_name")]
#> input_name common_name
#> 1 Quercus robur Stiel-Eiche
#> 2 Fagus sylvatica Rotbuche
#> 3 Abies alba Weiß-Tanne
#> 4 Arrhenatherum elatius Glatthafer
#> 5 Plantago lanceolata Spitz-Wegerich
#> Sources: COL 2026.09, vernacular names 2026.10 | cite() for full citationsadd_trait() gathers one trait from every dataset that
has it and returns it in one unit and one vocabulary.
list_traits() lists the traits it knows:
traits <- list_traits()
nrow(traits)
#> [1] 211
head(traits[order(-traits$n_sources), c("trait", "unit", "n_sources")])
#> trait unit n_sources
#> 21 body_length mm 19
#> 13 body_mass g 15
#> 69 diet_guild <NA> 12
#> 14 longevity yr 11
#> 16 clutch_litter_size offspring per clutch/litter 10
#> 2 seed_mass mg 8By default the sources are combined by their median into one value per row, with columns for the unit, the sources used, their number, and the smallest and largest value:
seed <- add_trait(res, "seed_mass")
#> add_trait('seed_mass'): diaz 5, gift 5, austraits 1, bien 5, brot 4, ecoflora 5, kew_sid 5, leda 5 (of 5 resolved names).
seed[, c("accepted_name", "seed_mass", "seed_mass_unit", "seed_mass_n",
"seed_mass_min", "seed_mass_max")]
#> accepted_name seed_mass seed_mass_unit seed_mass_n seed_mass_min
#> 1 Quercus robur 3489.136038 mg 7 1444.9500
#> 2 Fagus sylvatica 211.702128 mg 7 127.5600
#> 3 Abies alba 55.100000 mg 7 38.3608
#> 4 Arrhenatherum elatius 2.756200 mg 6 1.5984
#> 5 Plantago lanceolata 1.393807 mg 8 0.2900
#> seed_mass_max
#> 1 5000.0000
#> 2 410.0000
#> 3 140.0000
#> 4 5.2400
#> 5 2.8376
#> Sources: COL 2026.09, Diaz et al. 2022 2026.08, GIFT (Weigelt et al. 2020) 2026.08, AusTraits (Falster et al. 2021) 2026.08, BIEN (Maitner et al. 2018) 2026.08, BROT 2.0 (Tavsanoglu & Pausas 2018) 2026.08, Ecoflora (Fitter & Peat 1994) 2026.08, Kew SID (RBG Kew) 2026.08, LEDA Traitbase (Kleyer et al. 2008) 2026.08 | cite() for full citationsA numeric trait is reported in one unit: GIFT records seed mass in
grams and the data of Díaz et al. in milligrams, and both are converted
to milligrams. trait_info() lists the sources of a trait in
their default order, the column each is read from and the conversion
applied; the first two are shown here:
info <- trait_info("seed_mass")
#> Seed mass (numeric, mg) | default priority: diaz > gift > austraits > bien > brot > ecoflora > kew_sid > leda
info[1:2, c("source", "column", "note")]
#> source column note
#> 1 diaz seed_mass_mg Milligrams.
#> 2 gift gift_seed_mass_mean GIFT grams converted to milligrams (x1000).mode = "wide" keeps one column per source, after each
source’s units and terms are converted to one unit and one
vocabulary:
wd <- add_trait(res, "woodiness", mode = "wide")
#> add_trait('woodiness'): zanne 5, gift 5, austraits 3, bien 5 (of 5 resolved names).
wd[, c("accepted_name", "woodiness_zanne", "woodiness_gift",
"woodiness_bien")]
#> accepted_name woodiness_zanne woodiness_gift woodiness_bien
#> 1 Quercus robur woody woody woody
#> 2 Fagus sylvatica woody woody woody
#> 3 Abies alba woody woody woody
#> 4 Arrhenatherum elatius non-woody non-woody non-woody
#> 5 Plantago lanceolata non-woody non-woody non-woody
#> Sources: COL 2026.09, Zanne et al. 2014 2026.08, GIFT (Weigelt et al. 2020) 2026.08, AusTraits (Falster et al. 2021) 2026.08, BIEN (Maitner et al. 2018) 2026.08 | cite() for full citationsEach source’s own words for woodiness are translated into one
vocabulary: Zanne et al. write herbaceous, as
add_zanne() showed, and add_trait() reports
non-woody.
Sources that measure a trait by different methods are not averaged.
When trait_info() notes a caution for one of the sources,
the values of the most complete source are reported, with a caution
column beside them, so a value never mixes two methods.
Three arguments change how sources are used. sources
restricts a trait to some of them, and priority sets their
order. combine sets how they are combined: the median, the
mean, the first or the most complete source, a vote, the smallest or the
largest value.
With provenance = TRUE, add_trait() adds a
<trait>_refs column listing the references behind
each value, as <dataset>:<id>:
seed_refs <- add_trait(res, "seed_mass", provenance = TRUE,
verbose = FALSE)
seed_refs$seed_mass_refs[3]
#> [1] "brot:Peman2012|gift:10191|gift:10255|leda:1ed7e1dccf64"cite() on those identifiers prints the references:
refs <- cite(seed_refs$seed_mass_refs[3])
#> ── taxify references ────────────────────────────────────────────────────────────
#> [brot:Peman2012] Pemán, J., Navarro, R. M., Nicolás, J. L., Prada, M. A., Serrada, R. (2012). Producción y manejo de semillas y plantas forestales. Parques Nacionales, Ministerio de Agricultura, Alimentación y Medio Ambiente.
#> [gift:10191] Kleyer, Bekker, Knevel, Bakker, Thompson, Sonnenschein, Poschlod, van Groenendael, Klimeš, Klimešová, Klotz, Rusch, Hermy, Adriaens, Boedeltje, Bossuyt, Dannemann, Endels, Götzenberger, Hodgson, Jackel, Kühn, Kunzmann, Ozinga, Römermann, Stadler, Schlegelmilch, Steendam, Tackenberg, Wilmann, Cornelissen, Eriksson, Garnier & Peco (2008) The LEDA Traitbase: a database of life-history traits of the Northwest European flora. Journal of Ecology 96, 1266–1274.
#> [gift:10255] Royal Botanic Gardens Kew (2016) Seed information database (SID). Available at: http://data.kew.org/sid/, last accessed 22/03/2013.
#> [leda:1ed7e1dccf64] BIOLFLOR database
#> ────────────────────────────────────────────────────────────The references are those the source datasets record for each value, as they record them.
Six species from six groups (an oak, a bird, a mammal, a toad, a fungus, a fish) each get one dataset per group:
mixed <- c("Quercus robur", "Parus major", "Vulpes vulpes", "Bufo bufo",
"Amanita muscaria", "Salmo trutta")
mx <- taxify(mixed, backbone = "col", verbose = FALSE)
mx <- mx |> add_zanne() |> add_avonet() |> add_pantheria() |>
add_amphibio() |> add_fungal_traits() |> add_fishbase()
#> add_avonet(): attaching 11 of 35 columns. Pass cols = "all" for all, or see enrichment_cols("avonet").
#> add_pantheria(): attaching 8 of 53 columns. Pass cols = "all" for all, or see enrichment_cols("pantheria").
#> add_amphibio(): attaching 13 of 35 columns. Pass cols = "all" for all, or see enrichment_cols("amphibio").
#> add_fungal_traits(): attaching 9 of 27 columns. Pass cols = "all" for all, or see enrichment_cols("fungal_traits").
#> add_fishbase(): attaching 15 of 246 columns. Pass cols = "all" for all, or see enrichment_cols("fishbase").
mx[, c("input_name", "woodiness", "avonet_body_mass_g",
"pantheria_body_mass_g", "body_size_mm", "primary_lifestyle",
"fb_trophic_level")]
#> input_name woodiness avonet_body_mass_g pantheria_body_mass_g
#> 1 Quercus robur woody NA NA
#> 2 Parus major <NA> 16.25 NA
#> 3 Vulpes vulpes <NA> NA 4820.36
#> 4 Bufo bufo <NA> NA NA
#> 5 Amanita muscaria <NA> NA NA
#> 6 Salmo trutta <NA> NA NA
#> body_size_mm primary_lifestyle fb_trophic_level
#> 1 NA <NA> NA
#> 2 NA <NA> NA
#> 3 NA <NA> NA
#> 4 150 <NA> NA
#> 5 NA ectomycorrhizal NA
#> 6 NA <NA> 3.36
#> Sources: COL 2026.09, Zanne et al. 2014 2026.08, AVONET 2026.08, PanTHERIA 2026.08, AmphiBIO 2026.08, FungalTraits 2026.08, FishBase 2026.08 | cite() for full citationsEach species has values only from the datasets that cover its group.
A column with NA in every row usually means the dataset
does not cover the group; an NA in some rows means the
species is not in the dataset, was described after it was compiled, or
was recorded at another rank. summary() counts the rows
each dataset filled, with its version and licence:
summary(mx)
#> ── taxify results ────────────────────────────────────────────────────────────
#> backbone: COL v2026.09 | 6 names submitted
#>
#> matched 6 (exact: 6, case-insensitive: 0, fuzzy: 0, abbrev: 0)
#> ────────────────────────────────────────────────────────────
#> taxon groups: animal: 4 angiosperm: 1 fungus: 1
#>
#> enrichments:
#> zanne (Zanne et al. 2014 2026.08) — 1 of 6 matched [CC0]
#> avonet (AVONET 2026.08) — 1 of 6 matched [CC BY 4.0]
#> pantheria (PanTHERIA 2026.08) — 1 of 6 matched [CC0]
#> amphibio (AmphiBIO 2026.08) — 1 of 6 matched [CC BY 4.0]
#> fungal_traits (FungalTraits 2026.08) — 1 of 6 matched [CC BY 4.0]
#> fishbase (FishBase 2026.08) — 1 of 6 matched [CC BY-NC 4.0]Each function joins the dataset on the accepted name of each row. A name entered as a synonym therefore receives the values the dataset holds for its accepted name, and an unmatched name receives none.
Backbones can accept different names for one species. When a dataset
is built, every name in it is matched against each of the
19
backbones, and the dataset holds a row under every accepted name any
backbone gives, so the join works whichever backbone matched the result.
When a row still finds nothing, it is matched again against the other
installed backbones and the join is retried under their accepted names;
the message reports how many rows were recovered this way, and
options(taxify.cross_backbone_recovery = FALSE) turns it
off. A dataset that holds values only for a broader taxon than the
matched one, or for a taxon the matched backbone accepts separately,
leaves the row empty and says so in its message.
Some datasets are keyed on the genus, such as FungalTraits (Polme et al. 2020), and join on the genus of each row. Hybrids and aggregates take values from their parents or their binomial, as described in Hybrids and aggregates.
Each dataset is downloaded on first use into
taxify_data_dir() and read from disk after that.
taxify_download_enrichment() fetches datasets ahead of
time:
A dataset with static = TRUE in
list_enrichments() is a fixed release and is never updated.
The others are checked against the published version once per session
and replaced when a newer one exists; the replaced build is kept, so
taxify_restore() can reinstall it. The version used is
shown by summary(), cited by cite() and
written by taxify_lock(), as in Get started.
The backbones and datasets: every dataset with its scope, version, licence and reference.
Joining your own data:
add_data() for tables of your own.
Hybrids and aggregates: values for hybrid and aggregate names.
Dengler J, Jansen F, Chusova O, Hullbusch E, Novak P, Van Meerbeek K, Axmanova I, Bruun HH, Chytry M, Guarino R, et al. (2023). Ecological Indicator Values for Europe (EIVE) 1.0. Vegetation Classification and Survey 4: 7-29. https://doi.org/10.3897/VCS.98324
Zanne AE, Tank DC, Cornwell WK, Eastman JM, Smith SA, FitzJohn RG, McGlinn DJ, O’Meara BC, Moles AT, Reich PB, et al. (2014). Three keys to the radiation of angiosperms into freezing environments. Nature 506: 89-92. https://doi.org/10.1038/nature12872