| Title: | Rainfall and Temperature Anomaly Indices for Climate Analysis |
|---|---|
| Description: | Computes rainfall anomaly indices and a standardised temperature anomaly from monthly or annual precipitation and temperature data supplied by the user. The rainfall indices are the Rainfall Anomaly Index (RAI; Van Rooy, 1965), the Modified Rainfall Anomaly Index (MRAI) and the Standardized Rainfall Anomaly Index (SRAI) of Ekpetere (2025) <doi:10.1016/j.jenvman.2025.124160>, the Simplified Standardized Precipitation Index (SSPI) of Raziei (2021) <doi:10.1016/j.jhydrol.2021.126761>, and the Standardized Precipitation Index (SPI; McKee et al., 1993). The temperature anomaly is a z-score computed within each calendar month. All indices are computed group-wise, so the user can stratify by any combination of spatial units (state, district, grid cell) and calendar month, and each value can be classified into a descriptive severity class. |
| Authors: | Md Yeasin [aut], Ranjit Kumar Paul [aut, cre], Pushkar Bora [aut] |
| Maintainer: | Ranjit Kumar Paul <[email protected]> |
| License: | GPL-3 |
| Version: | 1.0.0 |
| Built: | 2026-10-16 17:40:16 UTC |
| Source: | https://github.com/cran/ClimateAnomaly |
ClimateAnomaly provides a unified interface for computing six widely-used rainfall anomaly indices and a standardised temperature anomaly from any user-supplied monthly or annual climate data frame.
| Function | Index | Reference |
calc_rai |
Rainfall Anomaly Index (RAI) | Van Rooy (1965) |
calc_mrai |
Modified RAI (MRAI) | Ekpetere (2025) |
calc_srai |
Standardized RAI (SRAI) | Ekpetere (2025) |
calc_sspi |
Simplified SPI (SSPI) | Raziei (2021) |
calc_spi |
Standardized Precipitation Index (SPI) | McKee et al. (1993) |
calc_temp_anomaly |
Temperature anomaly z-score | (none) |
The convenience wrapper calc_all_indices computes all of
the above in a single call on a user-supplied data frame, grouped by any
combination of spatial and temporal identifiers.
library(ClimateAnomaly)
# Load your own data (must have at least a precipitation column
# plus grouping columns such as state/district/grid and month)
my_data <- read.csv("my_climate_data.csv")
result <- calc_all_indices(
data = my_data,
group_cols = c("state", "month_num"), # or c("district", "month_num")
rain_col = "rainfall_mm",
tmax_col = "tmax_c", # NULL to skip temperature
tmin_col = "tmin_c"
)
The input data frame must contain:
One or more grouping columns (e.g. state,
month_num).
A precipitation column (numeric, mm).
Optionally, tmax and tmin columns (numeric, degrees Celsius).
No fixed column names are required; you pass the actual names as arguments.
Maintainer: Ranjit Kumar Paul [email protected]
Authors:
Ranjit Kumar Paul [email protected]
Md Yeasin
Pushkar Bora
Van Rooy, M.P. (1965). A rainfall anomaly index independent of time and
space. Notos, 14, 97–104.
Ekpetere, K.O. (2025). Development and evaluation of the modified and
standardized rainfall anomaly indices for extreme variability analysis.
Journal of Environmental Management, 375, 124160.
doi:10.1016/j.jenvman.2025.124160
Raziei, T. (2021). Revisiting the Rainfall Anomaly Index to serve as a
Simplified Standardized Precipitation Index.
Journal of Hydrology, 602, 126761.
doi:10.1016/j.jhydrol.2021.126761
Raziei, T. (2022). Improving the normalization procedure of the simplified
standardized precipitation index (SSPI) using Box-Cox transformation.
Stochastic Environmental Research and Risk Assessment, 37, 925–951.
doi:10.1007/s00477-022-02317-9
McKee, T.B., Doesken, N.J., & Kleist, J. (1993). The relationship of
drought frequency and duration to time scales.
Proc. 8th Conf. Applied Climatology, AMS, 179–184.
This is the main user-facing function. It accepts a data frame (or
data.table / tibble) with monthly (or annual) climate records
and computes all six anomaly indices in one call, stratified by any
combination of grouping columns the user specifies.
calc_all_indices( data, group_cols = c("state", "month_num"), rain_col = "rainfall_mm", tmax_col = "tmax_mean_c", tmin_col = "tmin_mean_c", indices = c("RAI", "MRAI", "SRAI", "SSPI", "SPI", "TEMP"), n_extreme = 10L, classify = TRUE )calc_all_indices( data, group_cols = c("state", "month_num"), rain_col = "rainfall_mm", tmax_col = "tmax_mean_c", tmin_col = "tmin_mean_c", indices = c("RAI", "MRAI", "SRAI", "SSPI", "SPI", "TEMP"), n_extreme = 10L, classify = TRUE )
data |
A |
group_cols |
Character vector of column names that define the groups
over which indices are computed. Typical: |
rain_col |
Name of the precipitation column. Default |
tmax_col |
Name of the maximum temperature column (optional).
Default |
tmin_col |
Name of the minimum temperature column (optional).
Default |
indices |
Character vector specifying which indices to compute.
Any subset of |
n_extreme |
Integer. Passed to |
classify |
Logical. If |
The function applies each index to every group defined by
group_cols. In the typical use case, group_cols = c("state",
"month_num") so that every index is computed relative to the long-term
climatology of each state in each calendar month.
The user must supply column names for:
precipitation (rain_col)
maximum temperature (tmax_col), optional
minimum temperature (tmin_col), optional
Columns that are NULL are simply skipped and not added to the output.
The original data with additional columns appended:
RAI, RAI_class
Rainfall Anomaly Index + label
MRAI, MRAI_class
Modified RAI + label
SRAI, SRAI_class
Standardized RAI + label
SSPI, SSPI_class
Simplified SPI + label
SPI, SPI_class
Standardized Precipitation Index + label
tmax_anomaly, tmax_anom_class
Tmax z-score + label (if tmax_col supplied)
tmin_anomaly, tmin_anom_class
Tmin z-score + label (if tmin_col supplied)
tavg_cMean of the tmax and tmin columns (if both T columns supplied)
tavg_anomaly, tavg_anom_class
Tavg z-score + label (if both T columns supplied)
Van Rooy, M.P. (1965). Notos, 14, 97–104.
Ekpetere, K.O. (2025). J. Env. Mgmt., 375, 124160.
doi:10.1016/j.jenvman.2025.124160
Raziei, T. (2021). J. Hydrology, 602, 126761.
doi:10.1016/j.jhydrol.2021.126761
McKee, T.B. et al. (1993). 8th Conf. Applied Climatology, AMS, 179–184.
calc_rai, calc_mrai,
calc_srai, calc_sspi, calc_spi,
calc_temp_anomaly
# --- Example with built-in sample dataset --- data(india_monthly) result <- calc_all_indices( data = india_monthly, group_cols = c("state", "month_num"), rain_col = "rainfall_mm", tmax_col = "tmax_mean_c", tmin_col = "tmin_mean_c" ) # View first few rows for one state subset(result, state == "Maharashtra" & year >= 2015, select = c("state","year","month_num","rainfall_mm", "RAI","MRAI","SPI","tmax_anomaly")) # --- Compute only RAI and SPI (skip temp) --- result2 <- calc_all_indices( data = india_monthly, group_cols = c("state", "month_num"), rain_col = "rainfall_mm", tmax_col = NULL, tmin_col = NULL, indices = c("RAI", "SPI") )# --- Example with built-in sample dataset --- data(india_monthly) result <- calc_all_indices( data = india_monthly, group_cols = c("state", "month_num"), rain_col = "rainfall_mm", tmax_col = "tmax_mean_c", tmin_col = "tmin_mean_c" ) # View first few rows for one state subset(result, state == "Maharashtra" & year >= 2015, select = c("state","year","month_num","rainfall_mm", "RAI","MRAI","SPI","tmax_anomaly")) # --- Compute only RAI and SPI (skip temp) --- result2 <- calc_all_indices( data = india_monthly, group_cols = c("state", "month_num"), rain_col = "rainfall_mm", tmax_col = NULL, tmin_col = NULL, indices = c("RAI", "SPI") )
Computes the Modified Rainfall Anomaly Index (MRAI) proposed by
Ekpetere (2025). Unlike RAI, MRAI uses the absolute minimum and
maximum of the full record as reference thresholds, removing the arbitrary
choice of the top/bottom 10 values and ensuring the index always lies
within .
calc_mrai(x)calc_mrai(x)
x |
Numeric vector of precipitation values for a single group. |
Numeric vector of MRAI values in .
Ekpetere, K.O. (2025). Development and evaluation of the modified and standardized rainfall anomaly indices for extreme variability analysis. Journal of Environmental Management, 375, 124160. doi:10.1016/j.jenvman.2025.124160
set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) mrai_values <- calc_mrai(rain) data.frame(rain = rain, MRAI = round(mrai_values, 3))set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) mrai_values <- calc_mrai(rain) data.frame(rain = rain, MRAI = round(mrai_values, 3))
Computes the Rainfall Anomaly Index (RAI) introduced by Van Rooy (1965).
The index ranks positive and negative precipitation anomalies through a
normalisation that uses the mean of the n_extreme highest values
() and the mean of the n_extreme lowest values
() as reference thresholds.
calc_rai(x, n_extreme = 10L)calc_rai(x, n_extreme = 10L)
x |
Numeric vector of precipitation values for a single group (e.g. one station and one calendar month over all years). |
n_extreme |
Integer. Number of extreme values used to compute the upper
( |
where is the current value, is the long-term mean,
is the mean of the n_extreme highest values, and
is the mean of the n_extreme lowest values.
Numeric vector of RAI values (same length and order as x).
Van Rooy, M.P. (1965). A rainfall anomaly index independent of time and space. Notos, 14, 97–104.
calc_mrai, calc_srai,
calc_all_indices
set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) rai_values <- calc_rai(rain) data.frame(rain = rain, RAI = round(rai_values, 3))set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) rai_values <- calc_rai(rain) data.frame(rain = rain, RAI = round(rai_values, 3))
Computes the Standardized Precipitation Index (SPI) of McKee et al. (1993).
A Gamma distribution is fitted via maximum-likelihood estimation to the
non-zero precipitation values; zero-inflation is handled explicitly through
the mixed probability .
The resulting cumulative probability is converted to a standard normal
z-score, which is the SPI value.
calc_spi(x)calc_spi(x)
x |
Numeric vector of precipitation values for a single group. |
If fewer than 4 non-zero observations are available (e.g. an arid month
with almost no rain), the function falls back to a simple z-score
.
Numeric vector of SPI values (standard normal scores).
McKee, T.B., Doesken, N.J., & Kleist, J. (1993). The relationship of drought frequency and duration to time scales. Proceedings of the 8th Conference on Applied Climatology, 17–22 January 1993, Anaheim, CA. American Meteorological Society, pp. 179–184.
set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) spi_values <- calc_spi(rain) data.frame(rain = rain, SPI = round(spi_values, 3))set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) spi_values <- calc_spi(rain) data.frame(rain = rain, SPI = round(spi_values, 3))
Computes the Standardized Rainfall Anomaly Index (SRAI) introduced by
Ekpetere (2025). SRAI incorporates the standard deviation ()
of the series to better detect extreme rainfall events relative to average
conditions. Output is clamped to .
calc_srai(x, clamp = TRUE)calc_srai(x, clamp = TRUE)
x |
Numeric vector of precipitation values for a single group. |
clamp |
Logical. If |
Numeric vector of SRAI values.
Ekpetere, K.O. (2025). Development and evaluation of the modified and standardized rainfall anomaly indices for extreme variability analysis. Journal of Environmental Management, 375, 124160. doi:10.1016/j.jenvman.2025.124160
set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) srai_values <- calc_srai(rain) data.frame(rain = rain, SRAI = round(srai_values, 3))set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) srai_values <- calc_srai(rain) data.frame(rain = rain, SRAI = round(srai_values, 3))
Computes the Simplified Standardized Precipitation Index (SSPI) as proposed by Raziei (2021). SSPI is designed as a non-parametric alternative to SPI that handles zero-dominated precipitation series (arid/semi-arid climates) without fitting a probability distribution.
calc_sspi(x, eps = 1e-06)calc_sspi(x, eps = 1e-06)
x |
Numeric vector of precipitation values for a single group. |
eps |
Small positive constant used in the denominator to prevent
division by zero in zero-dominated series. Default |
The algorithm follows Equation (2) of Raziei (2021):
Compute the probability of zero precipitation (PZP).
Reduce skewness of the series:
If skewness : apply cube-root transformation
().
If skewness : apply cube transformation
().
Otherwise: no transformation.
Compute anomaly in the
transformed domain.
Derive the 5th () and 95th () percentiles of
the ranked transformed data.
Apply the appropriate SSPI formula based on the sign of
and whether PZP 40%.
Numeric vector of SSPI values.
Raziei, T. (2021). Revisiting the Rainfall Anomaly Index to serve as a Simplified Standardized Precipitation Index. Journal of Hydrology, 602, 126761. doi:10.1016/j.jhydrol.2021.126761
set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) sspi_values <- calc_sspi(rain) data.frame(rain = rain, SSPI = round(sspi_values, 3))set.seed(42) rain <- c(120, 85, 200, 60, 150, 95, 170, 40, 110, 130, 75, 220, 90, 160, 50, 140, 100, 180, 70, 115) sspi_values <- calc_sspi(rain) data.frame(rain = rain, SSPI = round(sspi_values, 3))
Computes the standardised temperature anomaly (z-score) for a single group:
calc_temp_anomaly(x)calc_temp_anomaly(x)
x |
Numeric vector of temperature values for a single group. |
where is the long-term mean temperature for the group and
is its sample standard deviation. The grouping is typically
location calendar month so that, for example,
every January at a given station is compared only against other Januaries.
Numeric vector of standardised anomaly values (z-scores).
# Tmax values for one station, all Januaries 1980-2020 set.seed(7) tmax_jan <- rnorm(41, mean = 28, sd = 2) z <- calc_temp_anomaly(tmax_jan) summary(z)# Tmax values for one station, all Januaries 1980-2020 set.seed(7) tmax_jan <- rnorm(41, mean = 28, sd = 2) z <- calc_temp_anomaly(tmax_jan) summary(z)
Assigns a drought/wet severity class label to a numeric vector of RAI, MRAI, or SRAI values using the classification scheme of Van Rooy (1965) and Raziei (2021).
classify_rai(x)classify_rai(x)
x |
Numeric vector of RAI (or MRAI/SRAI) values. |
| Range | Class |
| >= 3.00 | Extremely Wet |
| 2.00 to 2.99 | Very Wet |
| 1.00 to 1.99 | Moderately Wet |
| 0.50 to 0.99 | Slightly Wet |
| -0.49 to 0.49 | Near Normal |
| -0.99 to -0.50 | Slightly Dry |
| -1.99 to -1.00 | Moderately Dry |
| -2.99 to -2.00 | Very Dry |
| <= -3.00 | Extremely Dry |
Character vector of class labels (same length as x).
Van Rooy, M.P. (1965). Notos, 14, 97–104. Raziei, T. (2021). Journal of Hydrology, 602, 126761.
vals <- c(-3.5, -2.1, -0.8, 0.1, 0.7, 1.5, 2.5, 3.2) classify_rai(vals)vals <- c(-3.5, -2.1, -0.8, 0.1, 0.7, 1.5, 2.5, 3.2) classify_rai(vals)
Assigns a drought/wet severity class label using the standard SPI classification (McKee et al., 1993).
classify_spi(x)classify_spi(x)
x |
Numeric vector of SPI or SSPI values. |
| Range | Class |
| >= 2.00 | Extremely Wet |
| 1.50 to 1.99 | Severely Wet |
| 1.00 to 1.49 | Moderately Wet |
| 0.50 to 0.99 | Mildly Wet |
| -0.49 to 0.49 | Near Normal |
| -0.99 to -0.50 | Mildly Dry |
| -1.49 to -1.00 | Moderately Dry |
| -1.99 to -1.50 | Severely Dry |
| <= -2.00 | Extremely Dry |
Character vector of class labels.
McKee, T.B., Doesken, N.J., & Kleist, J. (1993). Proceedings of the 8th Conference on Applied Climatology, AMS, pp. 179–184.
vals <- c(-2.5, -1.6, -1.2, -0.7, 0.0, 0.6, 1.1, 1.7, 2.3) classify_spi(vals)vals <- c(-2.5, -1.6, -1.2, -0.7, 0.0, 0.6, 1.1, 1.7, 2.3) classify_spi(vals)
Assigns a temperature departure class label to standardised temperature anomaly z-scores.
classify_temp_anomaly(x)classify_temp_anomaly(x)
x |
Numeric vector of temperature anomaly z-scores. |
| Range | Class |
| >= 2.0 | Extremely Warm |
| 1.0 to 1.99 | Warm |
| 0.5 to 0.99 | Slightly Warm |
| -0.49 to 0.49 | Near Normal |
| -0.99 to -0.50 | Slightly Cool |
| -1.99 to -1.00 | Cool |
| <= -2.0 | Extremely Cool |
Character vector of class labels.
vals <- c(-2.5, -1.2, -0.6, 0.1, 0.7, 1.3, 2.1) classify_temp_anomaly(vals)vals <- c(-2.5, -1.2, -0.6, 0.1, 0.7, 1.3, 2.1) classify_temp_anomaly(vals)
A subset of monthly state-level rainfall and temperature records for India, included as a demonstration dataset for the ClimateAnomaly package.
india_monthlyindia_monthly
A data frame with columns:
Character. State/territory name.
Integer. Year (1976–2026).
Integer. Calendar month (1 = January, 12 = December).
Character. Month label in "YYYY-MM" format.
Numeric. Monthly total rainfall (mm).
Integer. Number of rainy days in the month.
Numeric. Mean daily maximum temperature (degrees Celsius).
Numeric. Mean daily minimum temperature (degrees Celsius).
Numeric. Peak daily maximum temperature (degrees Celsius).
Numeric. Lowest daily minimum temperature (degrees Celsius).
Logical. Whether the month has complete data coverage.
Character. Data source identifier.
Open-Meteo historical climate API (open-meteo.com).
data(india_monthly) head(india_monthly) table(india_monthly$state)data(india_monthly) head(india_monthly) table(india_monthly$state)