Mann-Kendallのトレンド検定

統計学




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

参考

  1. R-project|Non-Parametric Trend Tests and Change-Point Detection
  2. Mann-Kendall 検定による水文時系列の傾向変動
  3. Design_Trend_Mann_Kendall
タイトルとURLをコピーしました