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.
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.
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 )
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 # 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 ]
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)
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 )
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")
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
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.