
Example
Yuxuan Wang
Sichuan Universitywyx1743@gmail.com
2026-10-11
Source:vignettes/Example.Rmd
Example.RmdOverview
VasGBIF provides a reproducible, tracheophyte-optimized, and computationally efficient framework for transforming GBIF records into analysis-ready datasets. The package functions are organized into 8 steps. This basic example demonstrates the complete workflow using the built-in example dataset.
Each step below progressively filters records through taxonomic, quality, and coordinate checks, so the dataset shrinks from the raw download to a high-quality, analysis-ready set.
library(VasGBIF)
library(data.table)
VasGBIF_summary <- list()Import Records
import_records() reads a GBIF occurrence download ZIP
(‘SIMPLE_CSV’ or Darwin Core Archive), extracts the occurrence table,
and returns an "import" data.table of the fields required
by the workflow. No records are filtered at this stage — the raw
issue column is preserved for the next step.
The built-in example dataset is a GBIF download of Medicago sativa (preserved specimens with coordinates, obtained 23 July 2026): https://doi.org/10.15468/dl.nt5exp.
gbif_file <- system.file(
"extdata", "0003386-260721160103020.zip",
package = "VasGBIF"
)
occ_import <- import_records(path = gbif_file)
VasGBIF_summary$initial_records <- nrow(occ_import)
VasGBIF_summary$initial_taxa <- uniqueN(occ_import$scientificName)
print(occ_import)The returned "import" object is a
data.table with the GBIF fields used by the workflow
(gbifID coerced to character, plus the raw
issue column).
Check Taxon Name
check_taxon() submits species- and infraspecific-rank
names to the Taxonomic Name Resolution Service (TNRS; Boyle et al. 2013)
for resolution against the World Checklist of Vascular Plants (WCVP) or
World Flora Online (WFO). Synonyms are resolved to accepted names;
records that fail the match-score threshold or lack an accepted/synonym
status are excluded from the downstream table and reported in the
summary for manual review.
taxa_checked <- check_taxon(occ_import = occ_import, accuracy = 0.85)
VasGBIF_summary$after_taxon_resolved <- nrow(taxa_checked$occ_taxa_checked)
VasGBIF_summary$final_taxa <- uniqueN(taxa_checked$occ_taxa_checked$Accepted_name)
print(taxa_checked)The occ_taxa object contains:
-
occ_taxa_checked: records with resolved taxonomy -
summary: one row per submitted name, for reviewing match quality -
runtime: execution time
Customized Filter
customized_filter() joins the imported records with the
resolved taxonomy and the parsed issue flags, then applies the enabled
filter rules to retain only high-quality records. By default the
countryCode, coordinateUncertainty (<=
10,000 m), and gbif_issues_max (<= 5) rules are enabled;
date, identifiedBy, and
recordedBy are opt-in. Every step is recorded in the
per-rule summary table.
filtered <- customized_filter(
occ_import = occ_import,
taxa_checked = taxa_checked
)
VasGBIF_summary$after_customized_filter <- nrow(filtered$occ_filtered)
print(filtered)The customFiltered object contains:
-
occ_filtered: the filtered occurrence table -
occ_marked: the records failed customized quality rules -
summary: per-rulerule,dropped, andremainingcounts
Clean Coordinates
par_clean_coordinates() validates coordinates with
CoordinateCleaner (Zizka et al. 2019) to flag spatial errors such as
centroids, capitals, marine coordinates, and zero coordinates, splitting
records into cleaned and problematic tables. Validation is parallelized
across user-specified threads.
cleaned_coordinates <- par_clean_coordinates(
input = filtered$occ_filtered,
species = 'Accepted_name_id',
latitude = 'decimalLatitude',
longitude = 'decimalLongitude',
threads = 8,tests = c("capitals", "centroids", "equal", "gbif", "institutions", "outliers", "seas", "zeros"))
VasGBIF_summary$cleaned <- nrow(cleaned_coordinates$CoordinateCleaned)
VasGBIF_summary$problematic <- nrow(cleaned_coordinates$CoordinateProblematic)
print(cleaned_coordinates)The CoordinateRefined object contains:
-
CoordinateCleaned: records with valid coordinates -
CoordinateProblematic: records failing one or more CoordinateCleaner tests (including those lack coordinates) -
runtime: execution time
Detect Native Status
detect_native_coord() and
detect_native_country() match each record against WCVP
distribution data (the internal Distributions dataset) via
WGSRPD Level 3 areas to classify it as native, introduced, extinct,
location_doubtful, or unknown. Records with validated coordinates are
matched spatially by detect_native_coord(); records without
coordinates or failed with cleaned_coordinates() are
matched through their country code by
detect_native_country(). Every classification records how
it was obtained in native_status_source.
native_detected_coord <- detect_native_coord(
input = cleaned_coordinates$CoordinateCleaned,
species = 'Accepted_name',
latitude = 'decimalLatitude',
longitude = 'decimalLongitude', buffer_km = 10, buffer_chunk_size = 2000)
native_detected_country <- detect_native_country(
input = cleaned_coordinates$CoordinateProblematic,
country = 'countryCode',
species = 'Accepted_name')
native_detected <- rbind(
native_detected_coord,
native_detected_country[is.na(decimalLatitude) | is.na(decimalLongitude),],
use.names = TRUE,
fill = TRUE
)
VasGBIF_summary$native <- native_detected[native_status == "native", .N]
VasGBIF_summary$introduced <- native_detected[native_status == "introduced", .N]
VasGBIF_summary$extinct <- native_detected[native_status == "extinct", .N]
VasGBIF_summary$location_doubtful <- native_detected[
native_status == "location_doubtful", .N
]
VasGBIF_summary$unknown <- native_detected[native_status == "unknown", .N]
print(native_detected)The nativeDetected objects are data.tables
keyed by gbifID. Each retains every column of the input
records and appends LEVEL3_COD, native_status,
native_status_source, and buffered. The
spatial result (native_detected_coord) carries coordinates
for every record and can be passed straight to
export_records() and map_records() without
joining back to cleaned_coordinates.
Map Visualiztion
map_records() renders the records on an interactive map
via mapview, with geohash-based decluttering and
colour-coding by native status.
map_records(
native_detected_coord = native_detected_coord,
precision = 3,
cex = 3
)Export Records
export_records() writes the classified records to disk
as two gzip-compressed CSV files:
-
all_records.csv.gz: all classified records with validated coordinates, with their native status -
native_records.csv.gz: the subset classified as native
export_records(
native_detected_coord = native_detected_coord,
native_detected_country = native_detected_country,
export_path = getwd()
)Summary
The summary statistics provide a quantitative overview of data reduction through the pipeline:
VasGBIF_summary |>
as.data.frame() |>
t()| Statistic | Description |
|---|---|
initial_records |
Total GBIF occurrence records imported |
initial_taxa |
Unique scientific names before resolution |
after_taxon_resolved |
Records retained after TNRS resolution (score and status thresholds) |
after_customized_filter |
Records retained after the quality filter rules |
cleaned |
Records with valid coordinates after CoordinateCleaner |
problematic |
Records failing one or more coordinate tests |
native |
Records classified as native |
introduced |
Records classified as introduced |
extinct |
Records classified as extinct |
location_doubtful |
Records classified as location_doubtful |
unknown |
Records with no usable distribution evidence |
final_taxa |
Unique accepted taxon names in the final dataset |
The workflow progressively filters the dataset through taxonomic
resolution, quality rules, and coordinate validation. The drop from
initial_records to after_customized_filter
reflects unresolved names and records failing the quality rules; the
drop from after_customized_filter to cleaned
reflects records that failed the coordinate tests being set aside
(records without coordinates are not carried by
clean_coordinates()); and the transition from
initial_taxa to final_taxa reflects taxonomic
resolution.
Performance
VasGBIF achieves its speed through:
-
C/C++ backends: core operations delegated to
data.table,stringi, andterra -
Vectorisation: issue-flag detection in
extract_issues()and native-status lookups indetect_native_coord()anddetect_native_country()process entire columns in compiled calls -
Memory-efficient design: in-place modification
(
:=,set()) avoids unnecessary copies -
Selective parallelisation:
par_clean_coordinates()distributes CoordinateCleaner validation across threads
On a standard laptop, VasGBIF compiles one million occurrence records within 15 minutes.
References
GBIF.org (23 July 2026) GBIF Occurrence Download https://doi.org/10.15468/dl.nt5exp