knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

Trait-based analysis is a standard procedure in community ecology and represents a good complement to taxonomic information. Some efforts have also been made to include trait-based metrics into current biomonitoring practices. The biomonitoR package provides functions to manipulate trait data and to calculate functional metrics (e.g. richness, diversity). Some examples on how to deal with functional analysis in biomonitoR will be provided.

Macroinvertebrates

For macroinvertebrates, biomonitoR provides by default the Tachet database (Tachet et al. 2010) available at freshwaterecology.info website. Briefly, the Tachet database is a fuzzy-coded database with 21 categories and a total of 113 modalities. One of the first steps in trait-based analysis is to retrieve trait information for the taxa present in the taxonomic dataset. There are some time-consuming steps when retrieving traits for macroinvertebrates because of inconsistencies between taxonomic resolution of the taxonomic dataset and those of traits. biomonitoR accomplish this task with the function assign_traits.

library(biomonitoR)

# import the example dataset in biomonitoR
# macro_ex includes taxa identified at species, genus and family level

data(macro_ex)

data_bio <- as_biomonitor(macro_ex)
data_agr <- aggregate_taxa(data_bio)


# use the assign_traits function

data_ts <- assign_traits( data_agr , tax_lev = "Taxa" )

# we can use assign_traits at the desired taxonomic level
# for example setting tax_lev = "Family"
# assign_traits does not allow taxonomic levels higher than families

assign_traits returns a data.frame reporting taxa names of the taxonomic dataset, the taxonomic level of each taxon of the taxonomic dataset, the name of the taxa whose traits have been associated to a taxon of the taxonomic dataset and the corresponding taxonomic level, the taxonomic distance between taxa of the taxonomic dataset and the one from trait dataset and traits. Taxonomic distance is calculated based on the taxonomic levels implemented in biomonitoR. There are some rules of aggregation that can be consulted on the help page of assign_traits.

# data.ts has more rows because more entries have been found for one or more taxa.
# only the first two traits are showed to not fill the page with numbers

data_ts[ 1:5 , 1:7 ]

The assign_traits function links available traits to a taxon by looking at the taxonomic tree. Multiple assignements for the same taxon can thus be obtained.

# data_ts has more rows because more entries have been found for one or more taxa.

dim(macro_ex)
dim(data_ts)

# look at Beraeidae for which five taxa of the trait dataset have been associated
# to one taxon of the taxonomic dataset

data_ts[data_ts$Taxa %in% "Beraeidae", 1:5]

Taxonomic distance can be useful, for example when only exact matches are needed. The filter_by_distance option of the assign_traits function or simple subsets can be used.

assign_traits( data_agr , filter_by_distance = 0 )[, 1:5 ]

data_ts[ data_ts$Taxonomic_distance == 0 , 1:5 ]

What to do next? biomonitoR offers a more advanced subsetting tool with the function manage_traits.

# select the traits belonging to the nearest taxa that have a taxonomic level equal or finer than the target one

data_ts_plus <- manage_traits( data_ts , method = "nearest+" , traceB = TRUE )

# with the traceB option set to TRUE you can check the taxa removed because they did not meet the requirments
# Here Serratella ignita is at species level while the trait at genus level (Serratella)

data_ts_plus$taxa_excluded

When you are satisfied with the list of taxa you can finalize your trait dataset with two strategies. The function average_traits allow the computation of the average traits for each Taxon. It is currently designed only for fuzzy data. For continuos data the default aggregate function can be used. Alternatively, taxa can be chosen randomly when multiple matches are available.

# take the average. If col_blocks is set to NULL the default values will be used.
# Please consider that the default value is correct only for the default trait dataset!
# only the first 5 rows and columns will be showed

data_ts_av <- average_traits( data_ts )
data_ts_av[ 1:5 , 1:5 ]

# alternatively a random selection can be done
# only the first 5 rows and  columns will be showed

sample_traits(data_ts)[ 1:5 , 1:5 ]

Now we have obtained a trait dataset that can be used for calculating functional metrics.

Functional indices

The calculation of functional dispersion, diversity, evenness, redundancy and richness are straightforward.

col_blocks <- c( 8, 7, 3, 9, 4, 3, 6, 2, 5, 3, 9, 8, 8, 5, 7, 5, 4, 4, 2, 3, 8 )

# functional dispersion
f_disp( data_agr , trait_db = data_ts_av , nbdim = 2 , type = "F" , col_blocks = col_blocks )

# functional diversity 
f_divs( data_agr , trait_db = data_ts_av , type = "F" , col_blocks = col_blocks )

# functional evenness
f_eve( data_agr , trait_db = data_ts_av , type = "F" , col_blocks = col_blocks )

# functional redundancy
f_red( data_agr , trait_db = data_ts_av , type = "F" , col_blocks = col_blocks )

# functional richness on 2 dimensions
f_rich( data_agr , trait_db = data_ts_av, nbdim = 2, type = "F", col_blocks = col_blocks )

The traceB option

Some information on the calculation is provided by the traceB option. This option is implemented in several biomonitoR functions to have a feedback on the calculation and to check if functions beahved as intended. It is particularly important for functional indices.

frich <- f_rich( data_agr , trait_db = data_ts_av , nbdim = 2 , type = "F" , col_blocks = col_blocks , traceB = TRUE )

# look at the traits with NA values
head( frich$NA_detection )

Community weighted mean and community specialization index

# community weighted mean and community specialization index
# only the first 5 columns are showed

cwm(x = data_agr, trait_db = data_ts_av, tax_lev = "Taxa", trans = log1p )[ , 1:5 ]
csi(x = data_agr, trait_db = data_ts_av, tax_lev = "Taxa", trans = log1p )[ , 1:5 ]

Working with distance matrices

Distance matrices can be provided instead of the functional database for calculating functional indices. Building distance matrices assure more flexibility and control. biomonitoR deals only fuzzy and continuous traits only, but other types of traits are frequent in ecological applications.

library( ade4 )

rownames( data_ts_av ) <- data_ts_av$Taxa
traits_prep <- prep.fuzzy( data_ts_av[ , -1 ], col.blocks = col_blocks )

traits_dist <- ktab.list.df( list( traits_prep ) )
traits_dist <- dist.ktab( traits_dist , type = "F" )

f_rich( data_agr , trait_db = traits_dist , nbdim = 2 )

Functional richness and dispersion require the construction of a functional space from distance/dissimilarity matrices. f_rich and f_disp do it internally through when a trait dataset is provided, but more control can be obtained by providing a distance matrix. The fuction select_pcoa_axes is a useful tool to select the number of axes needed to build the functional space with a desired quality. Three methods for evaluating the qauality of the functional space are proposed. select_pcoa_axes also evaluates the performances of different correction algorhitms when negative eigenvalues are found during the construction of the functional space.

select_pcoa_axes( traits_dist , method = "cor" , tresh = 0.7)
select_pcoa_axes( traits_dist , method = "legendre" , tresh = 0.65)
select_pcoa_axes( traits_dist , method = "maire" , tresh = 0.01)

Working at different taxonomic levels

One of the strength of biomonitoR is the ability to work at different taxonomic levels. The examples above were done at a mixed-taxonomic level (species, genus, family and order). If we wanto to look at the family level results, we can repeat the analysis by specifying famly in both assign_traits and indices.

data_fam_ts <- assign_traits( data_agr , tax_lev = "Family" )

data_fam_ts_av <- average_traits( data_fam_ts )

# functional richness
f_rich( data_agr , trait_db = data_fam_ts_av , tax_lev = "Family" , nbdim = 2 , type = "F" , col_blocks = col_blocks )

Macrophytes

The same approach used for macroinvertebrates can be used for other groups. The following example is for macrophytes.

# load macrophyte data
data(oglio)
data(traits_mf)

# importing data in the biomonitoR format
oglio.asb <- as_biomonitor(oglio, group = "mf", FUN = bin)
oglio.agg <- aggregate_taxa(oglio.asb)

# no need to run assign_traits, just to show its use
oglio.ts <- assign_traits( oglio.agg , trait_db = traits_mf , group = "mf" )
oglio.ts[ 1:5 , 1:5 ]

# create a distance matrix using the gowdis distance in the package FD
# other distances could be better, but for this example is enough

# load FD
library( FD )

# prepare the traits database
oglio_traits <- traits_mf
rownames( oglio_traits ) <- oglio_traits[ , "Taxa" ]
oglio_traits <- oglio_traits[ , ! colnames( oglio_traits ) %in% "Taxa" ]

# crea
oglio.dist <- gowdis( oglio_traits )

# select the number of axis according to legendre
select_pcoa_axes( oglio.dist , method = "legendre" )

# calculate functional richness
f_rich(oglio.agg, trait_db = oglio.dist, tax_lev = "Taxa", nbdim = 4, correction = "quasi")

REFERENCES

Schmidt-Kloiber, A., & Hering, D. (2015). An online tool that unifies, standardises and codifies more than 20,000 European freshwater organisms and their ecological preferences. Ecological Indicators, 53, 271-282.

Tachet H (2010) Invertébrés d’eau douce: Systématique, biologie, écologie, édition revue et augmentée. CNRS Editions, Paris



alexology/biomonitoR documentation built on April 7, 2024, 10:15 a.m.