knitr::opts_chunk$set( collapse = TRUE, comment = "#>", class.warning = "collapsable-warnings", warning = FALSE, fig.path = "perf-", fig.height = 8.5, fig.width = 8, message = FALSE, error = FALSE ) suppressPackageStartupMessages({ library("dplyr") library("ggplot2") })
This vignette presents some performance tests ran between fundiversity
and other functional diversity packages. Note that to avoid the dependency on other packages, this vignette is pre-computed.
Here is a table that summarizes the comparable functions (and their arguments) for functions included in fundiversity
. Note that the package name is indicated before ::
followed by the function name.
| Index Type | Index Name | Source | fundiversity
function | Equivalent Functions |
|:-----------------|:--------------------------------------------------|:------------------------------|:------------------------|----------------------|
| α-diversity | Functional Dispersion (FDis) | @Laliberte_distancebased_2010 | fd_fdis()
| ~~BAT::dispersion()
~~ (doesn't compute FDis)FD::fdisp()
~~hillR::hill_func()
~~ (actually rely on FD
for FDis computations and standardize the traits without telling the user)mFD::alpha.fd.multidim(..., ind_vect = "fdis")
|
| α-diversity | Functional Divergence (FDiv) | @Villeger_New_2008 | fd_fdiv()
| mFD::alpha.fd.multidim(..., ind_vect = "fdiv")
|
| α-diversity | Functional Evenness (FEve) | @Villeger_New_2008 | fd_feve()
| mFD::alpha.fd.multidim(..., ind_vect = "feve")
|
| α-diversity | Functional Richness (FRic) | @Villeger_New_2008 | fd_fric()
| BAT::alpha()
(tree, not strictly equal)BAT::hull.alpha()
(hull)mFD::alpha.fd.multidim(..., ind_vect = "fric")
|
| α-diversity | Rao's Quadratic Entropy (Q) | @Villeger_Decomposing_2013 | fd_raoq()
| adiv::QE()
BAT::rao()
hillR::hill_func()
(standardize traits without warning)mFD::alpha.fd.hill(..., q = 2, tau = "max")
(returns a slightly modified version of Q according to @Ricotta_Diversity_2009) |
| β-diversity | Functional Richness Intersection (FRic_intersect) | @Rao_Diversity_1982 | fd_fric_intersect()
| betapart::functional.beta.pair()
hillR::hill_func_parti_pairwise()
|
The other packages are thus: adiv
[@Pavoine_adiv_2020], BAT
[@Cardoso_BAT_2015], betapart
[@Baselga_betapart_2012], FD
[@Laliberte_FD_2014], hillR
[@Li_hillR_2018], and mFD
[@Magneville_mFD_2022]. For fairness of comparison, even if FD::dbFD()
contains most indices we're not considering it as it computes all indices together for each call, and would necessarily be slower.
We will now benchmark the functions included in fundiversity
with the corresponding function in other packages using the microbenchmark::microbenchmark()
function. We will use the fairly small (~220 species, 8 sites, 4 traits) provided dataset in fundiversity
.
tictoc::tic() # Time execution of vignette library(fundiversity) data("traits_birds", package = "fundiversity") data("site_sp_birds", package = "fundiversity") dist_traits_birds <- dist(traits_birds)
fdis_bench <- microbenchmark::microbenchmark( fundiversity = { fundiversity::fd_fdis(traits_birds, site_sp_birds) }, FD = { FD::fdisp(dist_traits_birds, site_sp_birds) }, mFD = { mFD::alpha.fd.multidim( traits_birds, site_sp_birds, ind_vect = "fdis", scaling = FALSE, verbose = FALSE, details_returned = FALSE ) }, times = 30 ) ggplot2::autoplot(fdis_bench) + labs(title = "Functional Dispersion (FDis)")
fdiv_bench <- microbenchmark::microbenchmark( fundiversity = fd_fdiv(traits_birds, site_sp_birds), mFD = mFD::alpha.fd.multidim( traits_birds, site_sp_birds, ind_vect = "fdiv", scaling = FALSE, verbose = FALSE ), times = 30 ) ggplot2::autoplot(fdiv_bench) + labs(title = "Functional Divergence (FDiv)")
feve_bench <- microbenchmark::microbenchmark( fundiversity = fd_feve(traits_birds, site_sp_birds), mFD = mFD::alpha.fd.multidim( traits_birds, site_sp_birds, ind_vect = "feve", scaling = FALSE, verbose = FALSE ), times = 30 ) ggplot2::autoplot(feve_bench) + labs(title = "Functional Evenness (FEve)")
fric_bench <- microbenchmark::microbenchmark( fundiversity = fd_fric(traits_birds, site_sp_birds), BAT_tree = BAT::alpha( site_sp_birds, traits_birds ), BAT_alpha_hull = BAT::hull.alpha( BAT::hull.build(site_sp_birds, traits_birds) ), mFD = mFD::alpha.fd.multidim( traits_birds, site_sp_birds, ind_vect = "fric", scaling = FALSE, verbose = FALSE ), times = 30 ) ggplot2::autoplot(fric_bench) + labs(title = "Functional Richness (FRic)")
fric_bench <- microbenchmark::microbenchmark( fundiversity = fd_fric_intersect(traits_birds, site_sp_birds) , betapart = betapart::functional.beta.pair( site_sp_birds, traits_birds ), hillR = hillR::hill_func_parti_pairwise( site_sp_birds, traits_birds, .progress = FALSE ), times = 30 ) ggplot2::autoplot(fric_bench) + labs(title = "Functional Richness Intersection (FRic)")
raoq_bench <- fric_bench <- microbenchmark::microbenchmark( fundiversity = fd_raoq(traits_birds, site_sp_birds), adiv= adiv::QE( site_sp_birds, dist_traits_birds ), BAT_rao = BAT::rao( site_sp_birds, distance = traits_birds ), hillR_hill_func = hillR::hill_func( site_sp_birds, traits_birds, fdis = FALSE ), mFD_alpha_fd_hill = mFD::alpha.fd.hill( site_sp_birds, dist_traits_birds, q = 2, tau = "max" ), times = 30 ) ggplot2::autoplot(raoq_bench) + labs(title = "Rao's Quadatric Entropy (Q)")
fundiversity
We now proceed to the performance evaluation of functions within fundiversity
with datasets of increasing sizes.
make_more_sp <- function(n) { traits <- do.call(rbind, replicate(n, traits_birds, simplify = FALSE)) row.names(traits) <- paste0("sp", seq_len(nrow(traits))) site_sp <- do.call(cbind, replicate(n, site_sp_birds, simplify = FALSE)) colnames(site_sp) <- paste0("sp", seq_len(ncol(site_sp))) list(tr = traits, si = site_sp) } null_sp_1000 <- make_more_sp(5) null_sp_10000 <- make_more_sp(50) null_sp_100000 <- make_more_sp(500)
bench_sp_fric <- microbenchmark::microbenchmark( species_200 = fd_fric( traits_birds, site_sp_birds), species_1000 = fd_fric( null_sp_1000$tr, null_sp_1000$si), species_10000 = fd_fric( null_sp_10000$tr, null_sp_10000$si), species_100000 = fd_fric(null_sp_100000$tr, null_sp_100000$si), times = 30 ) ggplot2::autoplot(bench_sp_fric) bench_sp_fric
bench_sp_fdiv <- microbenchmark::microbenchmark( species_200 = fd_fdiv( traits_birds, site_sp_birds), species_1000 = fd_fdiv( null_sp_1000$tr, null_sp_1000$si), species_10000 = fd_fdiv( null_sp_10000$tr, null_sp_10000$si), species_100000 = fd_fdiv(null_sp_100000$tr, null_sp_100000$si), times = 30 ) ggplot2::autoplot(bench_sp_fdiv) bench_sp_fdiv
bench_sp_raoq <- microbenchmark::microbenchmark( species_200 = fd_raoq( traits_birds, site_sp_birds), species_1000 = fd_raoq( null_sp_1000$tr, null_sp_1000$si), species_10000 = fd_raoq( null_sp_10000$tr, null_sp_10000$si), times = 30 ) ggplot2::autoplot(bench_sp_raoq) bench_sp_raoq
bench_sp_feve <- microbenchmark::microbenchmark( species_200 = fd_feve( traits_birds, site_sp_birds), species_1000 = fd_feve( null_sp_1000$tr, null_sp_1000$si), species_10000 = fd_feve( null_sp_10000$tr, null_sp_10000$si), times = 15 ) ggplot2::autoplot(bench_sp_feve) bench_sp_feve
all_bench_sp <- list(fric = bench_sp_fric, fdiv = bench_sp_fdiv, raoq = bench_sp_raoq, feve = bench_sp_feve) %>% bind_rows(.id = "fd_index") %>% mutate(n_sp = gsub("species_", "", expr) %>% as.numeric()) all_bench_sp %>% ggplot(aes(n_sp, time * 1e-9, color = fd_index)) + geom_point(alpha = 1/3) + geom_smooth() + scale_x_log10() + scale_y_log10() + scale_color_brewer(type = "qual", labels = c(fric = "FRic", fdiv = "FDiv", raoq = "Rao's Q", feve = "FEve")) + labs(title = "Performance comparison between indices", x = "# of species", y = "Time (in seconds)", color = "FD index") + theme_bw() + theme(aspect.ratio = 1)
make_more_sites <- function(n) { site_sp <- do.call(rbind, replicate(n, site_sp_birds, simplify = FALSE)) rownames(site_sp) <- paste0("s", seq_len(nrow(site_sp))) site_sp } site_sp_100 <- make_more_sites(12) site_sp_1000 <- make_more_sites(120) site_sp_10000 <- make_more_sites(1200)
bench_sites_fric <- microbenchmark::microbenchmark( sites_10 = fd_fric(traits_birds, site_sp_birds), sites_100 = fd_fric(traits_birds, site_sp_100), sites_1000 = fd_fric(traits_birds, site_sp_1000), sites_10000 = fd_fric(traits_birds, site_sp_10000), times = 15 ) ggplot2::autoplot(bench_sites_fric) bench_sites_fric
bench_sites_fdiv <- microbenchmark::microbenchmark( sites_10 = fd_fdiv(traits_birds, site_sp_birds), sites_100 = fd_fdiv(traits_birds, site_sp_100), sites_1000 = fd_fdiv(traits_birds, site_sp_1000), sites_10000 = fd_fdiv(traits_birds, site_sp_10000), times = 15 ) ggplot2::autoplot(bench_sites_fdiv) bench_sites_fdiv
bench_sites_raoq = microbenchmark::microbenchmark( sites_10 = fd_raoq(traits = NULL, site_sp_birds, dist_traits_birds), sites_100 = fd_raoq(traits = NULL, site_sp_100, dist_traits_birds), sites_1000 = fd_raoq(traits = NULL, site_sp_1000, dist_traits_birds), sites_10000 = fd_raoq(traits = NULL, site_sp_10000, dist_traits_birds), times = 15 ) ggplot2::autoplot(bench_sites_raoq) bench_sites_raoq
bench_sites_feve <- microbenchmark::microbenchmark( sites_10 = fd_feve(traits = NULL, site_sp_birds, dist_traits_birds), sites_100 = fd_feve(traits = NULL, site_sp_100, dist_traits_birds), sites_1000 = fd_feve(traits = NULL, site_sp_1000, dist_traits_birds), sites_10000 = fd_feve(traits = NULL, site_sp_10000, dist_traits_birds), times = 15 ) ggplot2::autoplot(bench_sites_feve) bench_sites_feve
all_bench_sites <- list(fric = bench_sites_fric, fdiv = bench_sites_fdiv, raoq = bench_sites_raoq, feve = bench_sites_feve) %>% bind_rows(.id = "fd_index") %>% mutate(n_sites = gsub("sites", "", expr) %>% as.numeric()) all_bench_sites %>% ggplot(aes(n_sites, time * 1e-9, color = fd_index)) + geom_point(alpha = 1/3) + geom_smooth() + scale_x_log10() + scale_y_log10() + scale_color_brewer(type = "qual", labels = c(fric = "FRic", fdiv = "FDiv", raoq = "Rao's Q", feve = "FEve")) + labs(title = "Performance comparison between indices", x = "# of sites", y = "Time (in seconds)", color = "FD index") + theme_bw() + theme(aspect.ratio = 1)
Session info of the machine on which the benchmark was ran and time it took to run
tictoc::toc( func.toc = function(x, y, msg) tictoc::toc.outmsg( x, y, paste0(msg, " seconds needed to generate this document") ) ) sessioninfo::session_info()
{js, echo=FALSE}
(function() {
var codes = document.querySelectorAll('.collapsable-warnings');
var code, i, d, s, p;
for (i = 0; i < codes.length; i++) {
code = codes[i];
p = code.parentNode;
d = document.createElement('details');
s = document.createElement('summary');
s.innerText = 'Warnings';
// <details><summary>Details</summary></details>
d.appendChild(s);
// move the code into <details>
p.replaceChild(d, code);
d.appendChild(code);
}
})();
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.