Pybeast
A Python package for Bayesian changepoint detection and time series decomposition
Install / Use
npx skills add zhaokg/PybeastInstalls into whichever agent you are using.
README
Rbeast: A Python package for Bayesian changepoint detection and time series decomposition
BEAST (Bayesian Estimator of Abrupt change, Seasonality, and Trend) is a fast, generic Bayesian model averaging algorithm to decompose time series or 1D sequential data into individual components, such as abrupt changes, trends, and periodic/seasonal variations, as described in <ins>Zhao et al. (2019)</ins>. BEAST is useful for changepoint detection (e.g., breakpoints, structural breaks, regime shifts, or anomalies), trend analysis, time series decomposition (e.g., trend vs seasonality), time series segmentation, and interrupted time series analysis. See a list of <a href="#publicationid"> selected studies using BEAST </a>.
Quick Installation
BEAST was impemented in C/C++ but accessible from R, Python, and Matlab. Run the following to install:
- Python:
pip install Rbeast - Matlab:
eval(webread('http://b.link/rbeast',weboptions('cert',''))) - R lang:
install.packages("Rbeast")
Quick Usage
One-liner code for Python, Matlab and R. Check below or github.com/zhaokg/Rbeast for more details.
# Python example
import Rbeast as rb; (Nile, Year)=rb.load_example('nile'); o=rb.beast(Nile,season='none'); rb.plot(o)
# Matlab example
load('Nile'); o = beast(Nile, 'season','none'); plotbeast(o)
# R example
library(Rbeast); data(Nile); o = beast(Nile); plot(o)
Installation for Python
<p align="left"> <a href= "https://github.com/zhaokg/Rbeast"> <img src="https://img.shields.io/static/v1?style=plastic&logo=github&label=see also&message=github.com/zhaokg/Rbeast&color=brightgreen" height="20"></a> </p>A package Rbeast has been deposited here at PyPI: https://pypi.org/project/Rbeast/. Run the command below in a console to install:
pip install Rbeast
Currently, a binary wheel file was built only for Windows and Python 3.8. For other OS platforms or Python versions, the installation requires a compiler to build the package from the C/C++ code, which is a hassle-free process in Linux (requiring gcc) or Mac (requiring xcode). If you want to force the installation from the source, please run:
pip install Rbeast --no-binary :none:
If needed, contact Kaiguang Zhao (zhao.1423@osu.edu) to help build the package for your specific OS platforms and Python versions.
Run and test Rbeast in Python
Import the Rbeast package as rb:
import Rbeast as rb
The first example is annual streamflow of the River Nile, starting from Year 1871. As annual observations, it has no periodic component (i.e., season='none').
nile, year = rb.load_example('nile')
o = rb.beast( nile, start=1871, season='none')
rb.plot(o, title='Annual streamflow of the Nile River')
rb.print(o)
o # see a list of output fields in the output variable o

The second example is a monthly time series of the Google Search popularity of beach over the US. This time series is reguarly-spaced (i.e., deltat=1 month =1/12 year); it has a cyclyic component with a period of 1 year (e.g., freq = period / deltat = 1 year / 1 month = 1/(1/12) = 12).
We follow R's terminology to use
freqto refer to the number of data points perperiod-- freq = period/deltaT; apparently, this differs from the standard definiton in physics -- freq = 1/period.
beach, year = rb.load_example('beach')
o = rb.beast(beach, start= 2004, deltat=1/12, freq =12)
rb.plot(o)
rb.print(o)
The third example is a stack of 484 satellite NDVI images over time, with a spatial dimenion of 10 rows x 20 cols: Each pixel is an irregular time series of 484 NDVI values with periodic variations at a period of 1.0 year. When running, BEAST will first aggragate the irregular time series into regular ones at a specified time interaval of deltat (in this example, we choose deltat=1/12 year =1 month, but you may choose other intervals, depending on the needs).
ndvi, year, datestr = rb.load_example('ndvi')
metadata = rb.args() # create an empty object to stuff the attributes: "metadata = lambda: None" also works
metadata.isRegular = False # data is irregularly-spaced
metadata.time = year # times of individulal images/data points: the unit here is fractional year (e.g., 2004.232)
metadata.deltaTime = 1/12 # regular interval used to aggregate the irregular time series (1/12 = 1/12 year = 1 month)
metadata.period = 1.0 # the period is 1.0 year, so freq= 1.0 /(1/12) = 12 data points per period
metadata.whichDimIsTime = 1 # the dimension of the input ndvi is (484,10,20): which dim refers to the time. whichDimIsTime is a 1-based index
o = rb.beast123(ndvi, metadata, [], [], []) # beast123(data, metadata, prior, mcmc, extra): default values used if not supplied
rb.print(o[5, 11]) # print the (6-th row, 12-th col) pixel: Python uses 0-based indices.
rb.plot(o[5, 11]) # plot the (6-th row, 12-th col) pixel: Python uses 0-based indices.
figure, axes = rb.plot(o[5, 11]) # plot the (6-th row, 12-th col) pixel: Python uses 0-based indices.
rb.plot( o[5, 12], fig = figure) # plot the (6-th row, 13-th col) pixel: Setting fig=figure will use the existing figure to plot
Below is another way to supply the time info:
ndvi, year, datestr = rb.load_example('ndvi')
metadata = lambda: None # create an empty object to stuff the attributes: "metadata = rb.args() " also works
metadata.isRegular = False # data is irregularly-spaced
metadata.time = rb.args( ) # create an empty object to stuff the 'datestr' and 'strfmt' attributes
metadata.time.datestr = datestr # datestr is a list of file names (e.g., s2_ndvi_2018-01-03.tif) that contain the date info
metadata.time.strfmt = 'xx_xxxx_YYYY-mm-dd.xxx' # the format used to extract the year (YYYY), month (mm), and day (dd) from the strings
metadata.deltaTime = 1/12 # regular interval used to aggregate the irregular time series (1/12 = 1/12 year = 1 month)
metadata.period = 1.0 # the period is 1.0 year, so freq= 1.0 /(1/12) = 12 data points per period
metadata.whichDimIsTime = 1 # the dimension of the input ndvi is (484,10,20): which dim refers to the time. whichDimIsTime is a 1-based index
extra = rb.args( # a set of options to specify the outputs or computational configurations
dumpInputData = True, # make a copy of the aggregated input data in the beast ouput
numThreadsPerCPU = 2, # Paralell computing: use 2 threads per cpu core
numParThreads = 0 # `0` means using all CPU cores: total num of ParThreads = numThreadsPerCPU * core Num
)
o = rb.beast123(ndvi, metadata, [], [], extra) # beast123(data, metadata, prior, mcmc, extra): default values used for prior and mcmc if missing
Description
Interpretation of time series data is affected by model choices. Different models can give different or even contradicting estimates of patterns, trends, and mechanisms for the same data–a limitation alleviated by the Bayesian estimator of abrupt change,seasonality, and trend (BEAST) of this package. BEAST seeks to improve time series decomposition by forgoing the "single-best-model" concept and embracing all competing models into the inference via a Bayesian model averaging scheme. It is a flexible tool to uncover abrupt changes (i.e., change-points), cyclic variations (e.g., seasonality), and nonlinear trends in time-series observations. BEAST not just tells when changes occur but also quantifies how likely the detected changes are true. It detects not just piecewise linear trends but also arbitrary nonlinear trends. BEAST is applicable to real-valued time series data of all kinds, be it for remote sensing, finance, public health, economics, climate sciences, ecology, and hydrology. Example applications include its use to identify regime shifts in ecological data, map forest disturbance and land degradation from satellite imagery, detect market trends in economic data, pinpoint anomaly and extreme events in climate data, and unravel system dynamics in biological data. Details on BEAST are reported in Zhao et al. (2019). The paper is available at https://go.osu.edu/beast2019.
Reference
-
Zhao, K., Wulder, M. A., Hu, T., Bright, R., Wu, Q., Qin, H., Li, Y., Toman, E., Mallick B., Zhang, X., & Brown, M. (2019). Detecting change-point, trend, and seasonality in satellite time series data to track abrupt changes and nonlinear dynamics: A Bayesian ensemble algorithm. Remote Sensing of Environment, 232, 111181. (the BEAST paper)
-
Zhao, K., Valle, D., Popescu, S., Zhang, X. and Mallick, B., 2013. Hyperspectral remote sensing of plant biochemistry using Bayesian model averaging with variable and band selection. Remote Sensing of Environment, 132, pp.102-119. (the mcmc sampler used for BEAST)
-
Hu, T., Toman, E.M., Chen, G., Shao, G., Zhou, Y., Li, Y., Zhao, K. and Feng, Y., 2021. Mapping fine-scale human disturbances in a working landscape with Landsat time series on Google Earth Engine. ISPRS Journal of Photogrammetry and Remote Sensing, 176, pp.250-261. (an application paper)
<a name=publication></a>
<h2 id="publicationid"> SelRelated Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.6kCommit, push, and open a PR
