Attaching published data

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.

  1. Find a dataset with list_enrichments(), or a trait with list_traits().

  2. Attach one dataset with its add_<source>() function.

  3. Gather one trait from several datasets with add_trait().

  4. Check coverage and versions with summary(), and cite the sources with cite().

library(taxify)

Finding a dataset

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   TRUE

Each 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).

Attaching one dataset

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 citations

enrichment_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 citations

Datasets with one value per place or language

Some 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 citations

Quercus 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 citations

add_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 citations

Nothofagus 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 citations

One trait from several datasets

add_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         8

By 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 citations

A 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 citations

Each 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.

Where each value came from

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.

Coverage

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 citations

Each 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]

How the values are joined

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.

Downloads and versions

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:

taxify_download_enrichment(c("zanne", "eive", "griis"))

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.

Where next

References

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