This vignette aims to describe several specific cases in the use of funbiogeo. It provides detailed examples of these uses. If you find your case is missing or if you have additional questions, please open an issue.
Working with Categorical Traits
Traits are not always continuous. While funbiogeo has been thought mainly to work with continuous trait data, it can also work with categorical trait data. This section describes how to use funbiogeo to work with categorical traits.
The default dataset provided in funbiogeo is an extract of the WOODIV database,
describing the diversity of Mediterrannean trees. It contains data for
28 species. To focus on categorical traits, we here propose to add three
more traits for each species: its leaf habit (whether is deciduous or
not?), its seed dispersal mode, and its shade tolerance. The next chunk
gives these traits for the 24 species. We coded seed dispersal as a
categorical trait with two modalities "anemochory" and
"endozoochory". We coded shade tolerance as a categorical
traits with five ordered levels "very_intolerant",
"intolerant", "moderately_tolerant",
"tolerant", and "very_tolerant". We first give
the complete dataset, and then randomly remove data points to show the
abilities of funbiogeo to display missing categorical traits.
woodiv_cat <- data.frame(
species = c(
'AALB', 'ACEP', 'ANEB', 'APIN', 'CLIB', 'CSEM', 'JCOM', 'JDEL', 'JMAC',
'JNAV', 'JOXY', 'JPHO', 'JTHU', 'PBRU', 'PHAL', 'PHEL', 'PINI', 'PMUG',
'PPIA', 'PPIR', 'PSYL', 'PUNC', 'TART', 'TBAC'
),
leaf_habit = c("evergreen"),
seed_dispersal = c(
"anemochory", "anemochory", "anemochory", "anemochory", "anemochory",
"anemochory", "endozoochory", "endozoochory", "endozoochory",
"endozoochory", "endozoochory", "endozoochory", "endozoochory",
"anemochory", "anemochory", "anemochory", "anemochory", "anemochory",
"endozoochory", "anemochory", "anemochory", "anemochory", "anemochory",
"endozoochory"
),
shade_tolerance = c(
"tolerant", "moderately_tolerant", "moderately_tolerant",
"moderately_tolerant", "moderately_tolerant", "intolerant", "intolerant",
"intolerant", "intolerant", "intolerant", "intolerant", "intolerant",
"intolerant", "very_intolerant", "very_intolerant", "intolerant",
"intolerant", "intolerant", "intolerant", "intolerant", "intolerant",
"intolerant", "very_intolerant", "very_tolerant"
)
)
head(woodiv_cat)
#> species leaf_habit seed_dispersal shade_tolerance
#> 1 AALB evergreen anemochory tolerant
#> 2 ACEP evergreen anemochory moderately_tolerant
#> 3 ANEB evergreen anemochory moderately_tolerant
#> 4 APIN evergreen anemochory moderately_tolerant
#> 5 CLIB evergreen anemochory moderately_tolerant
#> 6 CSEM evergreen anemochory intolerantThen to simulate missing trait data, we randomly remove 20% of the values:
# Randomly removes 20% of the values
set.seed(20260411)
woodiv_cat_na <- apply(
woodiv_cat[, 2:4], 2, function(x) {x[sample( c(1:24), floor(24/10))] = NA; x}
)
woodiv_cat_na <- as.data.frame(woodiv_cat_na)
woodiv_cat_na$species <- woodiv_cat$species
woodiv_cat_na <- woodiv_cat_na[, c(4, 1:3)]
woodiv_cat_na$shade_tolerance <- factor(
woodiv_cat_na$shade_tolerance,
levels = c("very_intolerant", "intolerant", "moderately_tolerant",
"tolerant", "very_tolerant"),
ordered = TRUE
)
head(woodiv_cat_na)
#> species leaf_habit seed_dispersal shade_tolerance
#> 1 AALB <NA> anemochory tolerant
#> 2 ACEP evergreen <NA> moderately_tolerant
#> 3 ANEB evergreen anemochory moderately_tolerant
#> 4 APIN evergreen anemochory moderately_tolerant
#> 5 CLIB evergreen anemochory moderately_tolerant
#> 6 CSEM evergreen anemochory intolerantWe can now use all of the functions of funbiogeo as with continuous trait data:
# Show trait completeness overall
fb_plot_species_traits_completeness(woodiv_cat_na)
# Map site completeness per trait
fb_map_site_traits_completeness(
woodiv_locations, woodiv_site_species, woodiv_cat_na
)
Note: the only two functions that won’t work with
categorical traits are fb_cwm() which computes an
abundance-weighted trait average, and
fb_plot_trait_correlation() which displays trait-trait
correlations.
Considering Intraspecific Variation
Trait-based ecology tends to present its frameworks and analyses with species average traits, most of its concepts can, however, apply to intraspecific trait variation, funbiogeo is no different. All of the examples, including the dataset provided with the package, show species average traits. In this section, we detail how to work with data that include intraspecific variation within funbiogeo. This should be fairly similar to what’s possible across other functional diversity R packages.
To include intraspecific variation, the user has to index species
within specific sites. For example, if they are three individuals of
Abies alba in site A, then the user has to provide
different names to the different individuals like
Abies_alba_1, Abies_alba_2, and
Abies_alba_3. These names have to be reused consistently
across objects site_species, species_traits,
and species_categories. As such, the user can define as
fine as possible intraspecific variation. It is also possible to provide
individual trait value for one or several sites and species average
trait for the rest of the sites, following the same idea as long as the
naming of species and invidivuals is consistent across objects. In this
case, the specified individuals will be counfounded as distinct species
in trait completeness plots.
Sites of Arbitrary Shapes
funbiogeo contains function that requires site-level data. A “site”
is here defined as any geographic grain in which the studied organisms
occur. Depending on the underlying scientific question, a site could be
a single geographic point, for example marking a precise sampled
location, or it could be a polygon (e.g., the area of a protected area),
or a (multi-)line (e.g., a transect or a sampling route), or a square in
a grid (e.g., through a sampling grid). The fb_map_*()
functions in funbiogeo are agnostic to the shape of the sites, meaning
they will work whatever the nature of the sites. The outputs will be
adapted to the nature of the sites. In this section, we will show
examples with sites of different types and see how this affects the
output given by funbiogeo mapping functions.
We will first select the 100 first sites in the
woodiv_locations object:
sampled_sites <- woodiv_locations[1:100,]
fb_map_site_traits_completeness(
sampled_sites, woodiv_site_species, woodiv_traits
)
We will now convert the sites to points by taking the centroid of
sites and use fb_map_*() functions to see how it will
affect their outputs:
# Convert all the sites into 'POINT' geometry
points_sites <- sf::st_centroid(sampled_sites)
#> Warning: st_centroid assumes attributes are constant over geometries
points_sites
#> Simple feature collection with 100 features and 2 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 2635000 ymin: 1745000 xmax: 2705000 ymax: 2045000
#> Projected CRS: ETRS89-extended / LAEA Europe
#> First 10 features:
#> site country geometry
#> 1 26351755 Portugal POINT (2635000 1755000)
#> 2 26351765 Portugal POINT (2635000 1765000)
#> 4 26351955 Portugal POINT (2635000 1955000)
#> 5 26351965 Portugal POINT (2635000 1965000)
#> 6 26451755 Portugal POINT (2645000 1755000)
#> 7 26451765 Portugal POINT (2645000 1765000)
#> 8 26451775 Portugal POINT (2645000 1775000)
#> 10 26451955 Portugal POINT (2645000 1955000)
#> 11 26451965 Portugal POINT (2645000 1965000)
#> 12 26451975 Portugal POINT (2645000 1975000)
# Map the sites
fb_map_site_traits_completeness(
points_sites, woodiv_site_species, woodiv_traits
)
As seen above, the sites are now actual points instead of the original squares. The function will adapt to the geometry of the sites provided by the user.
But funbiogeo can accommodate sites of any geometry, to show sites that represent lines, we will group sites into lines of sites and use the same function.
lines_sites = points_sites
# Assign groups to create 10 lines
site_ids <- data.frame(
site = points_sites$site,
group_line = rep(1:10, each = 10)
)
# Group sites geographically
lines_sites <- lines_sites |>
dplyr::inner_join(site_ids, by = "site") |>
dplyr::group_by(group_line) |>
dplyr::summarise(country = unique(country)) |>
sf::st_cast("LINESTRING") |>
dplyr::rename(site = group_line)
lines_sites
#> Simple feature collection with 10 features and 2 fields
#> Geometry type: LINESTRING
#> Dimension: XY
#> Bounding box: xmin: 2635000 ymin: 1745000 xmax: 2705000 ymax: 2045000
#> Projected CRS: ETRS89-extended / LAEA Europe
#> # A tibble: 10 × 3
#> site country geometry
#> <int> <chr> <LINESTRING [m]>
#> 1 1 Portugal (2635000 1755000, 2635000 1765000, 2635000 1955000, 2635000 1…
#> 2 2 Portugal (2645000 1985000, 2655000 1765000, 2655000 1775000, 2655000 1…
#> 3 3 Portugal (2655000 1995000, 2655000 2005000, 2655000 2015000, 2665000 1…
#> 4 4 Portugal (2665000 1855000, 2665000 1915000, 2665000 1925000, 2665000 1…
#> 5 5 Portugal (2675000 1775000, 2675000 1785000, 2675000 1805000, 2675000 1…
#> 6 6 Portugal (2675000 1935000, 2675000 1975000, 2675000 1985000, 2675000 2…
#> 7 7 Portugal (2685000 1865000, 2685000 1875000, 2685000 1895000, 2685000 1…
#> 8 8 Portugal (2685000 2025000, 2685000 2035000, 2695000 1755000, 2695000 1…
#> 9 9 Portugal (2695000 1895000, 2695000 1905000, 2695000 1925000, 2695000 1…
#> 10 10 Portugal (2695000 2025000, 2695000 2035000, 2695000 2045000, 2705000 1…
# Group sites in woodiv_site_species
woodiv_site_lines <- woodiv_site_species |>
dplyr::inner_join(site_ids) |>
dplyr::select(-site) |>
dplyr::rename(site = group_line) |>
dplyr::group_by(site) |>
dplyr::summarise(
dplyr::across(dplyr::everything(), \(x) as.numeric(sum(x) > 0))
)
#> Joining with `by = join_by(site)`
fb_map_site_traits_completeness(
lines_sites, woodiv_site_lines, woodiv_traits
)
The geometry now displays the lines, even though they are not the most perfect representation of the actual sites, but it shows the capabilities of funbiogeo.
Similarly to the upscaling vignette, the map functions can also accommodate larger polygons, for example by aggregating sites per country.
# Convert all sites to a single polygon
polygon_sites <- sampled_sites |>
dplyr::group_by(country) |>
dplyr::summarise(country = unique(country)) |>
sf::st_cast("MULTIPOLYGON") |>
dplyr::rename(site = country)
# Compute new site-species object
woodiv_site_polygon <- woodiv_site_species |>
subset(site %in% sampled_sites$site) |>
dplyr::select(-site) |>
dplyr::mutate(site = "Portugal") |>
dplyr::group_by(site) |>
dplyr::summarise(
dplyr::across(dplyr::everything(), \(x) as.numeric(sum(x) > 0))
)
# Display the map
fb_map_site_traits_completeness(
polygon_sites, woodiv_site_polygon, woodiv_traits
)
Now all of the sites are merged as a single big polygon.
Have fun with funbiogeo and if you have a question, an issue, or a suggestion, make sure to fill a report on GitHub.
