Skip to content

Commit 3d9101c

Browse files
authored
Add files via upload
1 parent 3ba2dfa commit 3d9101c

File tree

2 files changed

+496
-0
lines changed

2 files changed

+496
-0
lines changed

dim_spi_n.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
from __future__ import division
2+
import numpy as np
3+
import lmoments
4+
5+
6+
def dim_spi_n(values, scale_months, lower_limit=-3.09, upper_limit=3.09):
7+
'''
8+
:param values:
9+
:param scale_months:
10+
:param lower_limit:
11+
:param upper_limit:
12+
:return:
13+
'''
14+
15+
# replace the values array with sliding sums at the specified month scale
16+
values = get_sliding_sums(values, scale_months)
17+
18+
# compute gamma parameters using the specified month scale
19+
gamma_values = gamma_parameters(values, scale_months)
20+
21+
# replace the sums stored in the values array with fitted values
22+
probability = 0.0
23+
for month_index in range(scale_months - 1, len(values)):
24+
25+
calendarMonth = month_index % 12
26+
if values[month_index] != np.nan:
27+
28+
# compute the probability
29+
probability = lmoments.cdfgam(values[month_index], gamma_values[calendarMonth, :])
30+
31+
# convert the probability to a fitted value
32+
values[month_index] = lmoments.quanor(probability, (0.0, 1.0))
33+
34+
# return the fitted values clipped to the specified upper and lower limits
35+
return np.clip(values, lower_limit, upper_limit)
36+
37+
38+
def gamma_parameters(summed_monthly_values, scale_months):
39+
'''
40+
:param monthly_values:
41+
:param scale_months:
42+
:return:
43+
'''
44+
45+
# allocate the array of gamma parameters we'll return
46+
gamma_parameters = np.full((12, 2), np.nan, dtype=np.float64)
47+
48+
# process each calendar month's values separately
49+
for i in range(12):
50+
51+
# get the values for the calendar month
52+
calendar_month_sums = summed_monthly_values[i::12]
53+
54+
# strip out all the NaN values
55+
calendar_month_sums = calendar_month_sums[np.logical_not(np.isnan(calendar_month_sums))]
56+
57+
# get the non-zero values only (resulting array will still contain NaNs if present)
58+
nonzero_calendar_month_values = calendar_month_sums[np.nonzero(calendar_month_sums)]
59+
60+
# determine how many zeros there were
61+
number_of_sums = calendar_month_sums.shape[0]
62+
number_of_nonzeros = nonzero_calendar_month_values.shape[0]
63+
number_of_zeros = number_of_sums - number_of_nonzeros
64+
65+
# calculate the probability of zero, the first gamma parameter
66+
probability_of_zero = number_of_zeros / number_of_sums
67+
68+
if probability_of_zero>0.1:
69+
gamma_parameters[i, :] = 0.0
70+
else:
71+
# Fit gamma distribution
72+
try:
73+
LMU = lmoments.samlmu(nonzero_calendar_month_values)
74+
gamfit = lmoments.pelgam(LMU)
75+
gamma_parameters[i, :] = gamfit
76+
except:
77+
gamma_parameters[i, :] = 0.0
78+
79+
return gamma_parameters
80+
81+
82+
def get_sliding_sums(values, number_of_values_to_sum):
83+
'''
84+
Get the valid sliding summations using 1-D convolution. The initial (number_of_values_to_sum - 1) elements
85+
of the result array will be padded with np.NaN values.
86+
87+
:param values: the array of values over which we'll compute sliding sums
88+
:param number_of_values_to_sum: the number of values for which each sliding summation will encompass, for example if
89+
this value is 3 then the first two elements of the output array will contain the pad value and the third
90+
element of the output array will contain the sum of the first three elements, and so on
91+
:return: an array of sliding sums, equal in length to the input values array, left padded with NaN values
92+
'''
93+
# get the valid sliding summations with 1D convolution
94+
sliding_sums = np.convolve(values, np.ones(number_of_values_to_sum), mode='valid')
95+
96+
# pad the first (n - 1) elements of the array with NaN values
97+
return np.hstack(([np.nan]*(number_of_values_to_sum - 1), sliding_sums))

0 commit comments

Comments
 (0)