Mann-Kendallのトレンド検定
$$
S=\sum_{k=1}^{n-1} \sum_{j=k+1}^{n} sgn\left(X_{j}-X_{k}\right)
$$
$$
\sigma^{2}=\frac{n(n-1)(2 n+5)-\sum_{j=1}^{p} t_{j}\left(t_{j}-1\right)\left(2 t_{j}+5\right)} {18}
$$
$$
Z=\left\{\begin{array}{cl}{\frac{S-1}{\sigma}} & {\text { if } \quad S>0} \\ {0} & {\text { if } \quad S=0} \\ {\frac{S+1}{\sigma}} & {\text { if } \quad S>0}\end{array}\right.
$$
python
def Mann_Kendall(x, alpha=0.01):
x = x[~np.isnan(x)].reshape(-1)
n = len(x)
# calculate S
s = 0
for k in range(n - 1):
for j in range(k + 1, n):
s += np.sign(x[j] - x[k])
# calculate the unique data
unique_x = np.unique(x)
# calculate the var(s)
tp = np.zeros(unique_x.shape)
for i in range(len(unique_x)):
tp[i] = np.sum(unique_x[i] == x)
var_s = (n * (n - 1) * (2 * n + 5) + np.sum(tp * (tp - 1) * (2 * tp + 5))) / 18
if s > 0:
z = (s - 1) / np.sqrt(var_s)
elif s == 0:
z = 0
elif s < 0:
z = (s + 1) / np.sqrt(var_s)
# calculate the p_value
p = 2 * (1 - sp.stats.norm.cdf(abs(z))) # two tail test
h = abs(z) > sp.stats.norm.ppf(1 - alpha / 2)
if (z < 0) and h:
print('decreasing')
elif (z > 0) and h:
print('increasing')
else:
print('no trend')
return z, p