Beta Diversity Functions

Beta diversity is a fundamental concept in ecology that quantifies the variation in species composition between different plots, or over time. In the context of community ecology, beta diversity functions help to assess how community composition changes spatially or temporally.

The beta_diversity functions in MetaCommunityMetrics are adapted from the beta.div.comp function in the R package adespatial. These methods, originally developed by Legendre (2014), are implemented in Julia to provide a more efficient means of computation for large-scale datasets. The functions use indices from the Podani family, Jaccard-based indices, and Ruzicka-based indices to calculate total beta diversity and its components: replacement and richness difference.

Choosing the Right Function

  • Use beta_diversity for a general, comprehensive measure of beta diversity across your dataset. This function provides an overall assessment of how species composition varies between sites or over time, capturing both replacement (the turnover of species) and richness difference(the difference in species richness).
  • Use spatial_beta_div to compare local communities of a metacommunity across different spatial locations with individual species abundance in each site aggregated across all time points.
  • Use temporal_beta_div to compare metacommunities over time with individual species abundance aggregated across all sites.

The Functions

MetaCommunityMetrics.beta_diversityFunction
beta_diversity(mat::Matrix; quant::Bool) -> DataFrame

Calculate beta diversity decompositions for a given biodiversity data. This function supports both binary (occurrences) and quantitative (abundance) data.

Arguments

  • mat::Matrix: A matrix where each row represents a site and each column represents a species. The elements of the matrix should represent the occurrence or abundance of species.
  • quant::Bool: Specifies the data type for analysis. When false, treats data as occurrences, converting any quantitative values into binary values and applying Jaccard-based indices. When true, treats data as abundance data and applies Ruzicka-based indices.

Returns

  • DataFrame: A DataFrame with the following columns:
    • BDtotal: Total beta diversity, which captures the overall dissimilarity between local communities.
    • Repl: Replacement component of diversity, which reflects species turnover between sites: how much communities differ due to having different species compositions rather than different species counts.
    • RichDif: Richness difference component of diversity, which captures differences in the number of species between communities.

Details

  • Empty sites (empty rows in the matrix) have to be removed before calculation.
  • Species that did not occupy any sites in the data (empty columns in the matrix) have to be removed before calculation.
  • This function is a translation/adaptation of the beta.div.compfunction from the R packageadespatial`, licensed under GPL-3.
  • Original package and documentation available at: https://cran.r-project.org/web/packages/adespatial/index.html

Example

julia> using MetaCommunityMetrics, Pipe, DataFrames

julia> df = load_sample_data()
53352×12 DataFrame
   Row │ Year   Month  Day    Sampling_date_order  plot   Species  Abundance  Presence  Latitude  Longitude  standardized_temperature  standardized_precipitation 
       │ Int64  Int64  Int64  Int64                Int64  String3  Int64      Int64     Float64   Float64    Float64                   Float64                    
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     1 │  2010      1     16                    1      1  BA               0         0      35.0     -110.0                  0.829467                -1.4024
     2 │  2010      1     16                    1      2  BA               0         0      35.0     -109.5                 -1.12294                 -0.0519895
     3 │  2010      1     16                    1      4  BA               0         0      35.0     -108.5                 -0.409808                -0.803663
     4 │  2010      1     16                    1      8  BA               0         0      35.5     -109.5                 -1.35913                 -0.646369
     5 │  2010      1     16                    1      9  BA               0         0      35.5     -109.0                  0.0822                   1.09485
   ⋮   │   ⋮      ⋮      ⋮             ⋮             ⋮       ⋮         ⋮         ⋮         ⋮          ⋮                 ⋮                          ⋮
 53348 │  2023      3     21                  117      9  SH               0         0      35.5     -109.0                 -0.571565                -0.836345
 53349 │  2023      3     21                  117     10  SH               0         0      35.5     -108.5                 -2.33729                 -0.398522
 53350 │  2023      3     21                  117     12  SH               1         1      35.5     -107.5                  0.547169                 1.03257
 53351 │  2023      3     21                  117     16  SH               0         0      36.0     -108.5                 -0.815015                 0.95971
 53352 │  2023      3     21                  117     23  SH               0         0      36.5     -108.0                  0.48949                 -1.59416
                                                                                                                                                53342 rows omitted

julia> matrix_with_abundance = @pipe df |> 
           select(_, Not(:Year, :Month, :Day, :Longitude, :Latitude, :standardized_temperature, :standardized_precipitation, :Presence)) |> 
           filter(row -> row[:Sampling_date_order] == 1, _) |> 
           unstack(_, :Species, :Abundance, fill=0) |>  
           select(_, Not(:Sampling_date_order, :plot)) |> 
           Matrix(_) |> #convert the dataframe to a matrix
           _[:, sum(_, dims=1)[1, :] .!= 0] |> 
           _[sum(_, dims=2)[:, 1] .!= 0,:] 
15×5 Matrix{Union{Missing, Int64}}:
 1  0  0  0  0
 1  0  0  0  0
 1  0  0  0  0
 2  0  0  0  0
 1  0  0  1  0
 4  0  0  1  0
 1  0  0  0  0
 ⋮           
 0  0  0  2  0
 1  0  0  0  0
 0  0  0  1  0
 0  0  0  0  1
 0  0  1  0  0
 0  0  0  0  1

julia> matrix_with_presence =  @pipe df |> 
           select(_, Not(:Year, :Month, :Day, :Longitude, :Latitude, :standardized_temperature, :standardized_precipitation, :Abundance)) |> 
           filter(row -> row[:Sampling_date_order] == 1, _) |>
           unstack(_, :Species, :Presence, fill=0) |> 
           select(_, Not(:Sampling_date_order, :plot)) |> 
           Matrix(_) |> #convert the dataframe to a matrix      
           _[:, sum(_, dims=1)[1, :] .!= 0] |> 
           _[sum(_, dims=2)[:, 1] .!= 0,:]
15×5 Matrix{Int64}:
 1  0  0  0  0
 1  0  0  0  0
 1  0  0  0  0
 1  0  0  0  0
 1  0  0  1  0
 1  0  0  1  0
 1  0  0  0  0
 ⋮           
 0  0  0  1  0
 1  0  0  0  0
 0  0  0  1  0
 0  0  0  0  1
 0  0  1  0  0
 0  0  0  0  1

julia> result_using_abanduce_data_1 = beta_diversity(matrix_with_abundance; quant=true)
1×3 DataFrame
 Row │ BDtotal   Repl     RichDif  
     │ Float64   Float64  Float64  
─────┼─────────────────────────────
   1 │ 0.390317   0.2678  0.122517

julia> result_using_abanduce_data_2 = beta_diversity(matrix_with_abundance; quant=false)
1×3 DataFrame
 Row │ BDtotal   Repl      RichDif   
     │ Float64   Float64   Float64   
─────┼───────────────────────────────
   1 │ 0.357143  0.284127  0.0730159

julia> result_using_binary_data = beta_diversity(matrix_with_presence; quant=false)
1×3 DataFrame
 Row │ BDtotal   Repl      RichDif   
     │ Float64   Float64   Float64   
─────┼───────────────────────────────
   1 │ 0.357143  0.284127  0.0730159
source
MetaCommunityMetrics.spatial_beta_divFunction
spatial_beta_div(abundance::AbstractVector, time::AbstractVector, site::AbstractVector, species::AbstractVector; quant::Bool) -> DataFrame

Calculate the beta diversity decompositions in space based on species abundances or occurrences.

Arguments

  • abundance::AbstractVector: Vector representing the abundance or occurrence of species.
  • time::AbstractVector: Vector representing sampling dates.
  • site::AbstractVector: Vector representing site names or IDs.
  • species::AbstractVector: Vector representing species names or IDs.
  • quant::Bool: Specifies the data type for analysis. When false, treats data as binary presence/absence, converting any quantitative values and applying Jaccard-based indices. When true, treats data as abundance data and applies Ruzicka-based indices.

Returns

  • DataFrame: A DataFrame containing the values of total beta diversity, replacement, and richness difference components in space. Columns are spatial_BDtotal, spatial_Repl, and spatial_RichDif.

Details

  • This function uses the beta_diversity function to calculate beta diversity decompositions after aggregating individual species abundances/occurrences across time.
  • For binary data, the function calculates Podani family, Jaccard-based indices.
  • For quantitative data, the function calculates Podani family, Ruzicka-based indices.

Example

julia> using MetaCommunityMetrics, Pipe, DataFrames

julia> df = load_sample_data()
53352×12 DataFrame
   Row │ Year   Month  Day    Sampling_date_order  plot   Species  Abundance  Presence  Latitude  Longitude  standardized_temperature  standardized_precipitation 
       │ Int64  Int64  Int64  Int64                Int64  String3  Int64      Int64     Float64   Float64    Float64                   Float64                    
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     1 │  2010      1     16                    1      1  BA               0         0      35.0     -110.0                  0.829467                -1.4024
     2 │  2010      1     16                    1      2  BA               0         0      35.0     -109.5                 -1.12294                 -0.0519895
     3 │  2010      1     16                    1      4  BA               0         0      35.0     -108.5                 -0.409808                -0.803663
     4 │  2010      1     16                    1      8  BA               0         0      35.5     -109.5                 -1.35913                 -0.646369
     5 │  2010      1     16                    1      9  BA               0         0      35.5     -109.0                  0.0822                   1.09485
   ⋮   │   ⋮      ⋮      ⋮             ⋮             ⋮       ⋮         ⋮         ⋮         ⋮          ⋮                 ⋮                          ⋮
 53348 │  2023      3     21                  117      9  SH               0         0      35.5     -109.0                 -0.571565                -0.836345
 53349 │  2023      3     21                  117     10  SH               0         0      35.5     -108.5                 -2.33729                 -0.398522
 53350 │  2023      3     21                  117     12  SH               1         1      35.5     -107.5                  0.547169                 1.03257
 53351 │  2023      3     21                  117     16  SH               0         0      36.0     -108.5                 -0.815015                 0.95971
 53352 │  2023      3     21                  117     23  SH               0         0      36.5     -108.0                  0.48949                 -1.59416
                                                                                                                                                53342 rows omitted

julia> result_using_abanduce_data_1 = spatial_beta_div(df.Abundance, df.Sampling_date_order, df.plot, df.Species; quant=true)
1×3 DataFrame
 Row │ spatial_BDtotal  spatial_Repl  spatial_RichDif 
     │ Float64          Float64       Float64         
─────┼────────────────────────────────────────────────
   1 │        0.264822      0.121882         0.142939
        
julia> result_using_abanduce_data_2 = spatial_beta_div(df.Abundance, df.Sampling_date_order, df.plot, df.Species; quant=false)
1×3 DataFrame
 Row │ spatial_BDtotal  spatial_Repl  spatial_RichDif 
     │ Float64          Float64       Float64         
─────┼────────────────────────────────────────────────
   1 │        0.133035       0.05976        0.0732746

julia> result_using_binary_data = spatial_beta_div(df.Presence, df.Sampling_date_order, df.plot, df.Species; quant=false)
1×3 DataFrame
 Row │ spatial_BDtotal  spatial_Repl  spatial_RichDif 
     │ Float64          Float64       Float64         
─────┼────────────────────────────────────────────────
   1 │        0.133035       0.05976        0.0732746
source
MetaCommunityMetrics.temporal_beta_divFunction
temporal_beta_div(abundance::AbstractVector, time::AbstractVector, site::AbstractVector, species::AbstractVector;quant::Bool) -> DataFrame

Calculate the beta diversity decompositions in time based on species abundances or occurrences.

Arguments

  • abundance::AbstractVector: Vector representing the abundance or occurrence of species.
  • time::AbstractVector: Vector representing sampling dates.
  • site::AbstractVector: Vector representing site names or IDs.
  • species::AbstractVector: Vector representing species names or IDs.
  • quant::Bool: Specifies the data type for analysis. When false, treats data as occurrences, converting any quantitative values into binary values and applying Jaccard-based indices. When true, treats data as abundance data and applies Ruzicka-based indices.

Returns

  • DataFrame: A DataFrame containing the values of total beta diversity, replacement, and richness difference components in time. Columns are temporal_BDtotal, temporal_Repl, and temporal_RichDif.

Details

  • This function uses the beta_diversity function to calculate beta diversity decompositions after aggregating individual species abundances/occurrences across sites.
  • For binary data, the function calculates Podani family, Jaccard-based indices.
  • For quantitative data, the function calculates Podani family, Ruzicka-based indices.

Example

julia> using MetaCommunityMetrics, Pipe, DataFrames

julia> df = load_sample_data()
53352×12 DataFrame
   Row │ Year   Month  Day    Sampling_date_order  plot   Species  Abundance  Presence  Latitude  Longitude  standardized_temperature  standardized_precipitation 
       │ Int64  Int64  Int64  Int64                Int64  String3  Int64      Int64     Float64   Float64    Float64                   Float64                    
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     1 │  2010      1     16                    1      1  BA               0         0      35.0     -110.0                  0.829467                -1.4024
     2 │  2010      1     16                    1      2  BA               0         0      35.0     -109.5                 -1.12294                 -0.0519895
     3 │  2010      1     16                    1      4  BA               0         0      35.0     -108.5                 -0.409808                -0.803663
     4 │  2010      1     16                    1      8  BA               0         0      35.5     -109.5                 -1.35913                 -0.646369
     5 │  2010      1     16                    1      9  BA               0         0      35.5     -109.0                  0.0822                   1.09485
   ⋮   │   ⋮      ⋮      ⋮             ⋮             ⋮       ⋮         ⋮         ⋮         ⋮          ⋮                 ⋮                          ⋮
 53348 │  2023      3     21                  117      9  SH               0         0      35.5     -109.0                 -0.571565                -0.836345
 53349 │  2023      3     21                  117     10  SH               0         0      35.5     -108.5                 -2.33729                 -0.398522
 53350 │  2023      3     21                  117     12  SH               1         1      35.5     -107.5                  0.547169                 1.03257
 53351 │  2023      3     21                  117     16  SH               0         0      36.0     -108.5                 -0.815015                 0.95971
 53352 │  2023      3     21                  117     23  SH               0         0      36.5     -108.0                  0.48949                 -1.59416
                                                                                                                                                53342 rows omitted

julia> result_using_abanduce_data_1 = temporal_beta_div(df.Abundance, df.Sampling_date_order, df.plot, df.Species; quant=true)
1×3 DataFrame
 Row │ temporal_BDtotal  temporal_Repl  temporal_RichDif 
     │ Float64           Float64        Float64          
─────┼───────────────────────────────────────────────────
   1 │         0.311222      0.0995483          0.211674
        
julia> result_using_abanduce_data_2 = temporal_beta_div(df.Abundance, df.Sampling_date_order, df.plot, df.Species; quant=false)
1×3 DataFrame
 Row │ temporal_BDtotal  temporal_Repl  temporal_RichDif 
     │ Float64           Float64        Float64          
─────┼───────────────────────────────────────────────────
   1 │         0.206262      0.0693664          0.136895

julia> result_using_binary_data = temporal_beta_div(df.Presence, df.Sampling_date_order, df.plot, df.Species; quant=false)
1×3 DataFrame
 Row │ temporal_BDtotal  temporal_Repl  temporal_RichDif 
     │ Float64           Float64        Float64          
─────┼───────────────────────────────────────────────────
   1 │         0.206262      0.0693664          0.136895
source

References

  • Legendre, P. (2014). Interpreting the replacement and richness difference components of beta diversity. Global Ecology and Biogeography, 23(11), 1324-1334. https://doi.org:https://doi.org/10.1111/geb.12207