SPEI¶
The Standardized Precipitation Evapotranspiration Index (SPI) method fits a loglogistic distribution to the difference between precipitation and potential evapotranspiration values (P-PET), and maps the result to a normal distribution (z values), which correspond to the SPEI values. P-PET is usually resampled to one ore more months.
\(spei \geq 2.0\) |
extremely wet |
\(1.5 \leq spei < 2.0\) |
very wet |
\(1.0 \leq spei < 1.5\) |
moderately wet |
\(-1.0 \leq spei < 1.0\) |
near normal |
\(-1.5 \leq spei < -1.0\) |
moderately dry |
\(-2.0 \leq spei < -1.5\) |
severely dry |
\(spei \leq -2.0\) |
extremely dry |
Tutorial¶
P-PET refers to a time series of differences between precipitation and evapotranspiration of any frequency not higher than monthly (minutely, hourly, daily, weekly, or monthly).
spei()¶
Input is a list or numpy.array of P-PET values. The output is an array of same size with calculated SPEI values. Gaps in the input data (numpy.nan) are ignored and result a numpy.nan at the same position in the output array.
>>> import numpy as np
>>> import pandas as pd
>>> from caeli.drought_indices import spei, spei_monthly
>>> b = [236.78906908, 264.81174819, 206.07614488, 329.1471248, 229.76300328, 88.48107583,
... 222.12576411, 203.1740944, 194.24915861, 233.04840882, 203.03193236, 181.99807424,
... 228.55427209, 239.45338575, 316.16425044, 192.11761111, 173.18384051, 285.25591321,
... 275.19281235, 310.7161464, 348.84101779, 330.42774158, 163.55803563, 177.16544205,
... 359.67310805, 282.82742497, 191.03543726, 333.89194558, 163.25115185, 322.16858475]
>>> spei(b)
array([-0.05447834, 0.39161421, -0.55496029, 1.28044935, -0.16899123,
-2.21208646, -0.29378891, -0.60177122, -0.74448836, -0.11538335,
-0.60405976, -0.93656914, -0.18873257, -0.01121518, 1.11915418,
-0.7782526 , -1.07149926, 0.69786961, 0.54963214, 1.04873009,
1.50833784, 1.29587081, -1.21539086, -1.01091053, 1.62564314,
0.66256868, -0.79534214, 1.33715757, -1.21991663, 1.19488129])
>>> b = [np.nan, 264.81174819, 206.07614488, 329.1471248, 229.76300328, 88.48107583,
... 222.12576411, 203.1740944, 194.24915861, 233.04840882, 203.03193236, 181.99807424,
... 228.55427209, 239.45338575, 316.16425044, 192.11761111, 173.18384051, 285.25591321,
... 275.19281235, 310.7161464, 348.84101779, 330.42774158, 163.55803563, 177.16544205,
... 359.67310805, 282.82742497, 191.03543726, 333.89194558, np.nan, 322.16858475]
>>> spei(b).round(1)
array([ nan, 0.32, -0.61, 1.24, -0.23, -2.18, -0.36, -0.65, -0.79,
-0.18, -0.66, -0.98, -0.25, -0.08, 1.07, -0.82, -1.1 , 0.64,
0.48, 1. , 1.47, 1.25, -1.24, -1.05, 1.6 , 0.6 , -0.84,
1.3 , nan, 1.15])
spei_monthly()¶
Generating a pandas.DataFrame with random daily P-PET values:
>>> np.random.seed(1)
>>> index = pd.date_range('1990-01-01', '2019-12-31', freq='1d')
>>> values = np.random.normal(100, 70, len(index))
>>> values[values < 0] = 0.0
>>> df = pd.DataFrame({'P-PET': values}, index=index)
Given daily data, calculate monthly SPEI:
>>> df_spei = spei_monthly(df).round(1)
>>> with pd.option_context('display.max_rows', 4, 'display.max_columns', 8):
... print(df_spei)
...
P01 P02 P03 P04 ... SPEI09 SPEI10 SPEI11 SPEI12
year ...
1990 30.3 29.5 35.5 29.4 ... 0.4 -0.3 1.2 -1.4
1991 32.1 28.7 39.4 29.7 ... -0.4 -0.3 0.0 -0.6
... ... ... ... ... ... ... ... ... ...
2018 32.1 25.5 33.2 33.9 ... 1.8 0.9 -1.0 -0.8
2019 23.9 28.7 30.8 37.6 ... 0.8 -0.7 0.7 1.3
[30 rows x 24 columns]
Given daily data, calculate monthly SPEI for accumulated three months:
>>> df_spei = spei_monthly(df, aggregation=3).round(1)
>>> with pd.option_context('display.max_rows', 4, 'display.max_columns', 8):
... print(df_spei)
...
P01-03 P02-04 P03-05 P04-06 ... SPEI09-11 SPEI10-12 SPEI11-01 SPEI12-02
year ...
1990 95.3 94.3 100.1 97.4 ... 0.7 -0.6 -0.2 -0.8
1991 100.2 97.8 98.5 91.5 ... -0.4 -0.6 -0.4 -0.7
... ... ... ... ... ... ... ... ... ...
2018 90.9 92.6 97.0 96.7 ... 1.2 -0.6 -2.0 -1.8
2019 83.3 97.0 99.2 97.4 ... 0.5 0.8 NaN NaN
[30 rows x 24 columns]
Given daily data and list of months, calculate monthly SPI aggregating three months:
>>> df_spei = spei_monthly(df, aggregation=3, months=[1, 4, 7, 10]).round(1)
>>> with pd.option_context('display.max_rows', 4, 'display.max_columns', 8):
... print(df_spei)
...
P01-03 P04-06 P07-09 P10-12 SPEI01-03 SPEI04-06 SPEI07-09 SPEI10-12
year
1990 95.3 97.4 101.1 91.9 0.6 0.8 0.8 -0.6
1991 100.2 91.5 100.0 92.0 1.4 -0.3 0.6 -0.6
... ... ... ... ... ... ... ... ...
2018 90.9 96.7 100.8 91.7 -0.3 0.6 0.7 -0.6
2019 83.3 97.4 90.8 99.2 -1.8 0.7 -0.8 0.8
[30 rows x 8 columns]