
<!-- README.md is generated from README.Rmd. Please edit that file -->

# bean 🫛 <a href="https://paanwaris.github.io/bean/"><img src="man/figures/logo.png" alt="bean website" align="right" height="138"/></a>

Paanwaris Paansri and Luis E. Escobar

<!-- badges: start -->

[![R-CMD-check](https://github.com/paanwaris/bean/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/paanwaris/bean/actions/workflows/R-CMD-check.yaml)
<!-- badges: end -->

[![CRAN
status](https://www.r-pkg.org/badges/version/bean)](https://CRAN.R-project.org/package=bean)
[![downloads](https://cranlogs.r-pkg.org/badges/grand-total/bean)](https://cranlogs.r-pkg.org:443/badges/grand-total/bean)
[![Lifecycle:
experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)
[![License:
MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Ecological Motivation

The `bean` package provides a tool to address a fundamental challenge in
species distribution modeling (SDM, or ecological niche modeling, ENM):
**sampling bias**. Occurrence records for species are rarely collected
through a systematic, stratified process. Instead, they often cluster in
easily accessible areas (like roads and cities) or in well-studied
research sites. This spatial bias can translate into an **environmental
bias**, where the model incorrectly learns that the species is
associated with the environmental conditions of those heavily sampled
areas, rather than its true ecological requirements.

`bean` tackles this problem by thinning occurrence data in
**environmental space**. The goal is to create a more uniform
distribution of points across the species’ observed environmental niche,
reducing the influence of densely clustered records. This allows for the
construction of a more accurate **fundamental niche** volume, which can
then be projected into geographic space to create a less biased
prediction of area with environmental suitability.

The name `bean` reflects the core principle of the method: ensuring that
each “pod” (a grid cell in environmental space) contains only a
specified number of “beans” (occurrence points).

## Package Description

**bean** operates by shifting the focus from geographic space to
environmental space:

- **Environmental Gridding**: Divides the environmental hypercube into
  “pods”.

- **Objective Thinning**: Reduces clusters to a specified density per
  pod.

- **Niche Delineation**: Fits ellipsoids to thinned data to define the
  fundamental niche.

## Installing the Package

The development version of `bean` can be installed from GitHub:

``` r
# Install devtools if needed
if (!require("devtools")) install.packages("devtools")

# Install bean
devtools::install_github("paanwaris/bean")
```

To load the package:

``` r
library(bean)
```

## The bean Protocol: Step-by-Step

A typical `bean` workflow consists of these key steps:

### 1. Data Preparation

The `prepare_bean()` function cleans raw occurrence data by removing
missing coordinates and extracting environmental values from raster
layers. This ensures all subsequent analyses use a clean, scaled
dataset.

> See the [Preparing
> bean](https://paanwaris.github.io/bean/articles/data-preparation.html)
> vignette.

### 2. Objective Grid Resolution

Instead of arbitrary thinning, `find_env_resolution()` selects a
**kernel-density bandwidth** for each environmental variable
(Sheather–Jones plug-in by default, with Silverman and Scott rules also
available). The bandwidth is a statistically defensible choice for the
edge length of an environmental grid cell: it is the scale at which the
empirical density of observations becomes smooth.

> See the [Finding the environmental
> resolution](https://paanwaris.github.io/bean/articles/environmental-thinning.html)
> vignette.

### 3. Apply Thinning

`bean` offers two core thinning methods:

- Stochastic (`thin_env_nd`): Randomly samples one “bean” from each
  occupied “pod”.

- Deterministic (`thin_env_center`): Generates a new point at the exact
  center of every occupied grid cell.

> See the [Apply
> thinning](https://paanwaris.github.io/bean/articles/environmental-thinning.html)
> vignette.

### 4. Niche Delineation

The `fit_ellipsoid()` function formalizes the environmental niche by
fitting a bivariate or multivariate ellipse around the thinned points.

> See the [Niche
> delineation](https://paanwaris.github.io/bean/articles/niche-modeling.html)
> vignette.

Suitability projection back to geographic space is provided by the
companion package **nicheR**, which supplies a `predict()` method.
`bean_ellipsoid` objects carry the S3 class `"nicheR_ellipsoid"` as a
second class string, so once nicheR is attached its `predict()` method
dispatches on them automatically — no conversion step required. Until
nicheR is on CRAN, the ellipsoid’s `centroid`, `cov_matrix`, and
pre-computed `Sigma_inv` fields can be used directly with
`stats::mahalanobis()` to compute pixel-level distances on a raster
stack.

## Checking the Vignettes

For full demonstrations of the protocol, check the package vignettes:

``` r
# Data Preparation & Visualization
vignette("data-preparation")

# Objective Thinning in Environmental Space
vignette("environmental-thinning")

# Niche Delineation & Suitability Mapping
vignette("niche-modeling")
```

<br>

## Acknowledgments

The `bean` package was adapted from the excellent work done in the
**nicheR** package. We are incredibly grateful to the nicheR developers
for their robust framework, which allows `bean_ellipsoid` objects to
utilize their `predict()` methods. If you use the spatial projection
features in `bean`, please be sure to install and cite **nicheR**.

### Installing nicheR

`nicheR` is available on CRAN:

``` r
install.packages("nicheR")
library(nicheR)
```

### Citation

> Castaneda-Guzman, M., Hughes, C., Paansri, P., & Cobos, M. E. (2026).
> *nicheR: Ellipsoid-Based Virtual Niches and Visualization.* R package
> version 0.1.0. <https://github.com/castanedaM/nicheR>

## Note on AI usage

To maintain high standards of code quality and documentation, we have
used AI LLM tools in this package. We used these tools for grammatical
polishing and exploring technical implementation strategies for
specialized functions. We manually checked and tested all code and
documentation refined with these tools.

<br>
