Community Niche Position and Width Estimation Tools.
EcoNiche
EcoNiche is an R package for quantifying niche position and niche breadth under continuous, multidimensional environmental gradients.
Traditional niche breadth indices often treat sampling units as discrete states. However, real ecological gradients are continuous, multidimensional, and frequently confounded by covariates (e.g., climate, spatial structure, background environmental effects). EcoNiche provides a standardized workflow to estimate niche parameters within a constrained ordination framework while explicitly controlling for covariates.
The package is built around one central idea:
Estimate niche position and conditional niche breadth in a continuous environmental space, rather than across arbitrary discrete states.
To achieve this, EcoNiche implements three analytical modules with distinct roles:
1️⃣ CCA / partial-CCA (core framework)
This is the primary method of EcoNiche.
This workflow is based on canonical correspondence analysis (CCA) and partial CCA (pCCA) following Okie et al. (2015) and Feng et al. (2020).
It allows users to:
- Construct a composite environmental gradient from multiple predictors
- Quantify niche position as the abundance-weighted mean along the dominant constrained axis
- Quantify conditional niche breadth as abundance-weighted dispersion after covariate control
Conceptually:
- CCA defines the dominant environmental gradient associated with focal predictors.
- pCCA removes covariate structure (e.g., temperature, spatial effects) to reduce confounding.
- Species’ spread in this covariate-controlled space represents conditional niche breadth.
This framework is specifically designed for:
- Continuous gradients
- Multivariate environmental predictors
- Explicit covariate control
- Community-scale comparisons
2️⃣ GAM (nonlinear single-gradient modeling and species response curves)
The GAM module serves both as a validation tool and as a biologically interpretable response modeling framework.
It fits species-specific response curves along the composite environmental axis (typically CCA1), allowing:
- Estimation of gradient optima
- Extraction of response breadth (Breadth50)
- Assessment of nonlinear response structure
- Explicit visualization of species-specific response curves
This module serves three complementary purposes:
Cross-validation of ordination-based niche position
GAM-derived optima can be compared directly with CCA-based abundance-weighted means to evaluate positional consistency.Quantification of one-dimensional tolerance along the dominant composite gradient
Breadth50 provides a practical measure of effective response range along the main constrained axis.Visualization of individual species response curves
GAM explicitly models the abundance–environment relationship, allowing users to:- Identify unimodal vs. skewed response shapes
- Detect boundary-constrained optima
- Compare narrow vs. broad response profiles across taxa
- Interpret ecological strategies at the single-species level
Importantly, the GAM analysis is conducted within the same gradient coordinate system defined by CCA, ensuring conceptual consistency between ordination-based and response-curve-based niche estimation.
3️⃣ Levins’ niche breadth (discrete-state benchmark)
Levins’ index is implemented for comparison, not as the primary estimator.
EcoNiche provides two Levins implementations:
- Sample-defined states (classical formulation)
- Gradient-binned states (bins along the composite CCA axis)
These serve as sensitivity benchmarks to evaluate:
- Dependence on state definition
- Sensitivity to sampling structure
- Confounding with species commonness (occurrence frequency and total abundance)
In continuous-gradient contexts, Levins’ breadth may reflect occupancy or prevalence more than environmental tolerance. Therefore, it is included primarily for methodological comparison.
Conceptual structure of EcoNiche
- Analytical structure of EcoNiche. CCA/pCCA define a composite environmental gradient for estimating niche position and conditional niche breadth. GAM provides species response curves along the same axis, and Levins’ index serves as a discrete-state comparison.*
EcoNiche is designed as a modular analytical framework rather than a fixed analytical pipeline.
At its core, the framework is built on constrained ordination:
CCA / partial-CCA define the composite environmental gradient and estimate niche parameters in continuous multivariate space.
From this core framework, users may choose different complementary modules depending on their research question:
Core module: CCA / pCCA
Used to estimate:
- Niche position (abundance-weighted mean along the constrained axis)
- Conditional niche breadth (abundance-weighted dispersion after covariate control)
This module is recommended when:
- Environmental predictors are multidimensional
- Covariate control is required
- Continuous-gradient niche estimation is the primary objective
Optional module A: GAM
Used when users wish to:
- Visualize species-specific response curves
- Quantify nonlinear response shapes
- Extract one-dimensional optima and response breadth (Breadth50)
- Cross-validate ordination-based niche position
GAM operates along the composite gradient defined by CCA, ensuring consistency in coordinate space.
Optional module B: Levins’ breadth
Used when users wish to:
- Compute classical discrete-state niche breadth
- Compare continuous-gradient estimation with sample-defined states
- Evaluate sensitivity to binning or state definition
- Assess potential commonness-driven effects
Levins’ index is included primarily as a comparative benchmark rather than the primary estimator under continuous gradients.
In practice, users typically:
- Define focal environmental predictors and covariates.
- Estimate niche position and conditional niche breadth using CCA/pCCA.
- Optionally apply GAM for species-level response modeling.
- Optionally compute Levins’ breadth for methodological comparison.
This flexible structure allows researchers to tailor analyses to their ecological question while maintaining a coherent gradient-based coordinate system.
Package version: 0.9.0
Installation
Install the development version from GitHub
# install.packages("remotes")
remotes::install_github("zhoushuotao/EcoNiche")
Dependencies
EcoNiche imports:
- vegan (CCA / partial-CCA)
- mgcv (GAM)
- ggplot2 (plots)
Suggested:
- knitr, rmarkdown (vignettes)
- testthat, viridisLite
Data format (important)
Most functions assume the following:
1) otu: taxon-by-sample abundance table
- Rows = taxa (OTUs/ASVs/species)
- Columns = samples
- Values can be counts or relative abundances (non-negative)
otu[1:3, 1:3]
# S1 S2 S3
# OTU1 10 0 2
# OTU2 3 1 0
# OTU3 0 0 5
2) env: sample-by-environment table
- Rows = samples
- Columns = environmental variables
rownames(env)should matchcolnames(otu)(EcoNiche will align by intersection when relevant)
env[1:3, ]
# Temp pH SOC
# S1 15.2 6.7 2.31
# S2 18.1 6.3 1.90
# S3 12.4 6.8 3.05
3) group (only for group workflow)
- Named vector/factor of group labels
names(group)must be sample IDs
Quick start (toy example)
library(EcoNiche)
set.seed(1)
# OTU table: 50 taxa x 30 samples
otu <- matrix(rpois(50 * 30, lambda = 10), nrow = 50, ncol = 30)
rownames(otu) <- paste0("OTU", 1:50)
colnames(otu) <- paste0("S", 1:30)
# Environment table: 30 samples x 3 variables
env <- data.frame(
Temp = rnorm(30, 15, 3),
pH = rnorm(30, 6.5, 0.4),
SOC = rlnorm(30, 2, 0.3)
)
rownames(env) <- colnames(otu)
Workflow A: CCA / partial-CCA (multi-dimensional niche)
EcoNiche provides a controller function cca_workflow() and two explicit workflows:
cca_workflow_gradient()cca_workflow_group()
A1) Gradient workflow
Use when you want:
- a position axis from CCA (typically CCA1),
- a width axis from partial-CCA (conditioning on covariates),
- plus basic diagnostic plots.
res <- cca_workflow(
mode = "gradient",
otu = otu,
env = env,
sel = "Temp", # constrained variable(s) for the width axis (partial-CCA)
covariates = c("pH", "SOC") # variables for position axis (CCA) and as covariates in partial-CCA
)
# Species-level niche traits (position/width)
head(res$species$species)
# Plot: niche width vs niche position
res$species$plot
# Site niche position vs a gradient variable
res$gradient$plot
Choosing sel and covariates in CCA/pCCA
EcoNiche separates environmental predictors into:
sel— focal environmental variable(s) defining the primary constrained axiscovariates— conditioning variables used to control background structure
The appropriate choice depends on study design and ecological hypothesis.
Scenario 1: Sampling along a known focal gradient (hypothesis-driven design)
If samples were collected explicitly along a known environmental gradient (e.g., temperature, pH, elevation), that gradient should typically be treated as the focal predictor.
Example:
- Samples span a temperature gradient across latitude.
- Other variables (e.g., pH, NDVI) vary but are not the primary research focus.
Recommended setup:
sel = "Temperature"
covariates = c("pH", "NDVI")
Interpretation:
CCA constructs the dominant composite axis associated with the focal gradient.
pCCA controls for background covariates.
Niche position reflects species location along the focal gradient.
Conditional niche breadth reflects dispersion after removing background effects.
This setup is appropriate when the research question is:
How do species’ niches vary along temperature after accounting for other environmental structure?
Scenario 2: No predefined focal gradient (exploratory design)
If the dominant environmental structure is unclear, or multiple predictors are strongly correlated, a data-driven approach is recommended.
In this case:
Perform PCA on environmental variables.
Inspect loadings of PC1 and PC2.
Identify the dominant composite environmental structure.
Use this information to guide CCA/pCCA specification.
Example:
PC1 loads strongly on precipitation and moisture.
PC2 reflects soil chemistry.
You may then:
Use predictors associated with PC1 as sel
Use remaining structure as covariates
Or reduce dimensionality first via cca_prep_env()
This approach avoids arbitrarily selecting a single variable when gradients are inherently multivariate.
A2) Group workflow
Use when samples belong to groups (e.g., habitat types, treatments, regions) and you want group summaries.
group <- rep(c("A", "B", "C"), length.out = ncol(otu))
names(group) <- colnames(otu)
res_g <- cca_workflow(
mode = "group",
otu = otu,
env = env,
sel = "Temp",
covariates = c("pH", "SOC"),
group = group,
plot_type = "both" # "sample" / "group" / "both"
)
head(res_g$group$group_summary)
res_g$plot
Workflow B: GAM response curves along a single gradient
Use when your main question is:
For each taxon, what is the optimum along gradient X, and how wide is its response?
EcoNiche fits one GAM per taxon and reports (among others):
optimum_env(peak along the gradient)env50_min,env50_max,breadth50(50% peak breadth)
B1) Fit all taxa
gam_df <- gam_fit_model(
otu = otu,
env = env,
env_var = "Temp",
data_type = "count", # "auto" / "count" / "relative"
count_family = "nb", # "nb" / "poisson"
use_offset = TRUE, # offset = log(library size) for count mode
min_prev = 0.10,
min_total = 100,
k_spline = 5,
n_grid = 200,
verbose = TRUE
)
head(gam_df)
B2) Plot a single taxon
p <- gam_plot_species(
otu = otu,
env = env,
env_var = "Temp",
otu_id = "OTU1",
data_type = "count",
count_family = "nb",
add_ci = TRUE
)
p$plot
p$optimum_env
p$breadth50
B3) Sample-level summary (abundance-weighted mean breadth)
site_bw <- gam_calc_sitewidth(
otu = otu,
niche_df = gam_df,
width_col = "breadth50",
weight_mode = "auto"
)
head(site_bw)
Workflow C: Levins niche breadth
Levins breadth treats environments as discrete states and measures how evenly a taxon occupies these states.
EcoNiche supports:
C1) Samples as states (classic)
lev_samples <- niche_width_calc(
otu = otu,
env = env, # optional; used for aligning samples
method = "levins", # "levins" / "shannon" / "both"
standardize = TRUE,
min_occ = 3,
min_abund = 5
)
head(lev_samples)
C2) Gradient-binned states (recommended for continuous gradients)
Discretize a continuous gradient into bins, aggregate abundances within bins, then compute Levins breadth across bins.
lev_binned <- levins_calc_binned(
otu = otu,
env = env,
axis_var = "Temp",
nbin = 8,
bin_method = "equal_freq", # "equal_freq" (quantiles) or "equal_width"
agg_fun = "mean", # "mean" recommended; or "sum"
otu_mode = "auto",
min_occ = 3,
min_abund = 5
)
head(lev_binned)
C3) Community-mean Levins width vs gradient
lev_comm <- levins_calc_group(
otu = otu,
env = env,
levins_df = lev_binned,
grad = "Temp",
width_col = "levins_Bstd",
method = "loess",
make_plot = TRUE
)
head(lev_comm$data)
lev_comm$plot
C4) Position–width relationship (e.g., compare CCA position vs Levins width)
pos_df <- res$species$species
pos_df$OTU <- rownames(pos_df)
pos_width <- levins_plot_pos_width(
pos_df = pos_df,
levins_df = lev_binned,
id_col = "OTU",
pos_col = "NichePosition",
width_col = "levins_Bstd",
method = "lm",
make_plot = TRUE
)
pos_width$plot
Practical guidance (what to use when)
- Need covariate control + multi-dimensional niche → CCA / partial-CCA workflow
- Need interpretable optimum + breadth along one gradient → GAM workflow
- Need a classic breadth index / discrete states → Levins workflow
- Gradient is continuous but you still want Levins →
levins_calc_binned()(binned states)
Common pitfalls
Sample alignment
- Ensure
colnames(otu)andrownames(env)refer to the same sample IDs.
- Ensure
Rare taxa
- GAM fits can be unstable for very rare taxa. Use
min_prev,min_total, and/ormin_mean.
- GAM fits can be unstable for very rare taxa. Use
Counts vs relative abundance
- For counts, consider the offset (
use_offset=TRUE) to account for library size.
- For counts, consider the offset (
Numeric column indices
- Some functions support numeric indices (Galaxy-style conventions). To avoid confusion, prefer column names.
Vignette
A vignette exists under vignettes/ (currently titled “CoNiche workflow” due to legacy naming).
To build vignettes locally:
install.packages(c("knitr", "rmarkdown"))
devtools::build_vignettes()
API overview (exported functions)
CCA / partial-CCA
cca_workflow(),cca_workflow_gradient(),cca_workflow_group()cca_prep_env(),cca_fit_ordination()cca_calc_species(),cca_calc_gradient()cca_calc_group(),cca_plot_group_env()
GAM
gam_fit_model(),gam_plot_species(),gam_calc_sitewidth()
Levins
niche_width_calc()levins_calc_binned(),levins_calc_group(),levins_plot_pos_width()
Citation
If you use EcoNiche in a publication, please cite the software (and include the version):
Zhou S, Feng K, Deng Y. EcoNiche: Community Niche Position and Width Estimation Tools (R package), v1.0.1. GitHub: https://github.com/yedeng-lab/EcoNiche
(Replace with a formal paper citation if/when a methods manuscript is published.)
Contributing / Support
Issues and pull requests are welcome.
When reporting bugs, please include:
- a minimal reproducible example,
sessionInfo(),- dimensions of
otuandenv, - the exact error message / traceback.
License
MIT License (see LICENSE / LICENSE.md).
::contentReference[oaicite:0]{index=0}