基本原理
Mann-Kendall趋势检验是一种非参数的时间序列趋势性检验的方法。已经广泛应用于检验各种气象要素时间序列的趋势分析。该方法的优点是不要求样本遵从一定的分布,也不受少数异常值或缺失值的干扰。
对于时间序列Xt,n为数据样本的长度,则样本的时间序列为(x_1,x_2,...,
x_n),根据时间序列,确定其所有对偶值(x_i, x_j,
j>i)中xi与xj的大小关系。并作出如下假设:
原假设H0:序列中的数据是随机排列的
备择假设H1:序列中的数据存在上升或下降趋势
定义Man-Kendall趋势检验统计量S:
其中Sign()
为符号函数,计算公式为:
- 当时,统计量S大致服从正态分布,其均值为0,方差,标准化后得到检验统计量Z值如下:
- 趋势检验结果
|
2.58<Z |
极显著增加趋势 |
|
|
显著增加趋势 |
|
|
弱显著增加趋势 |
|
|
无明显增加趋势 |
|
Z |
无变化 |
|
|
无显著减少趋势 |
|
|
弱显著减少趋势 |
|
|
显著减少趋势 |
|
|
极显著增加趋势 |
此处也可参考博文Mann-kendall趋势分析
Mann-Kendall 算法(python)
以下为mann-Kendall趋势检验算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| # mk检验
def mk_test(x, alpha=0.05):
"""
This function is derived from code originally posted by Sat Kumar Tomer
(satkumartomer@gmail.com)
See also: http://vsp.pnnl.gov/help/Vsample/Design_Trend_Mann_Kendall.htm
The purpose of the Mann-Kendall (MK) test (Mann 1945, Kendall 1975, Gilbert
1987) is to statistically assess if there is a monotonic upward or downward
trend of the variable of interest over time. A monotonic upward (downward)
trend means that the variable consistently increases (decreases) through
time, but the trend may or may not be linear. The MK test can be used in
place of a parametric linear regression analysis, which can be used to test
if the slope of the estimated linear regression line is different from
zero. The regression analysis requires that the residuals from the fitted
regression line be normally distributed; an assumption not required by the
MK test, that is, the MK test is a non-parametric (distribution-free) test.
Hirsch, Slack and Smith (1982, page 107) indicate that the MK test is best
viewed as an exploratory analysis and is most appropriately used to
identify stations where changes are significant or of large magnitude and
to quantify these findings.
Input:
x: a vector of data
alpha: significance level (0.05 default)
Output:
trend: tells the trend (increasing, decreasing or no trend)
h: True (if trend is present) or False (if trend is absence)
p: p value of the significance test
z: normalized test statistics
Examples
--------
"""
if x[0] != -9999.0:
# 获取list的长度
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, tp = np.unique(x, return_counts=True) # 返回去重后的元素,并且返回去重元素的数量
g = len(unique_x)
# calculate the var(s)
if n == g: # there is no tie
var_s = (n * (n - 1) * (2 * n + 5)) / 18 # 如果每个元素唯一,则计算直接计算统计量s方差
else: # there are some ties in data # 如果有重复的元素
var_s = (n * (n - 1) * (2 * n + 5) - np.sum(tp * (tp - 1) * (2 * tp + 5))) / 18
# 计算z值
if s > 0:
z = (s - 1) / np.sqrt(var_s)
elif s < 0:
z = (s + 1) / np.sqrt(var_s)
else: # s == 0:
z = 0
# calculate the p_value
p = 2 * (1 - norm.cdf(abs(z))) # two tail test 两端检验
if abs(z) > norm.ppf(1 - alpha / 2):
h = 1 # 1 表示接受假设
else:
h = 0 # 0 表示拒绝假设
if (z < 0) and h: # 接受
trend = -1 # -1 表示下降趋势
elif (z > 0) and h: # 接受
trend = 1 # 1 表示上升趋势
else:
trend = 0 # 0 表示无趋势
else:
h = -9999.0
trend = -9999.0
p = -9999.0
z = -9999.0
return z, h
|
代码测试
作者采用华北平原1992年-2021年(共30年)的月降雨量进行测试,趋势检验结果如下所示:
结果分析
后续再补充。
问题总结
- 样本大小
在对时间序列进行检验时,要保证样本足够大,以确保趋势检验的结果具有统计学意义。
- 空间差异性
当研究区较小时,对全流域进行mann-kendall趋势检验,可能会出现均呈现统一的下降或增加的趋势,则空间差异性较差,不利于结果的讨论和分析。此时则可以选择线性规划的斜率来表征数据的趋势。