0%

使用Hexo搭建博客

Mann-Kendall趋势分析和Sen Median斜率估计

基本原理

Mann-Kendall趋势检验是一种非参数的时间序列趋势性检验的方法。已经广泛应用于检验各种气象要素时间序列的趋势分析。该方法的优点是不要求样本遵从一定的分布,也不受少数异常值或缺失值的干扰。

  1. 对于时间序列Xt,n为数据样本的长度,则样本的时间序列为(x_1,x_2,..., x_n),根据时间序列,确定其所有对偶值(x_i, x_j, j>i)中xi与xj的大小关系。并作出如下假设:

    原假设H0:序列中的数据是随机排列的 备择假设H1:序列中的数据存在上升或下降趋势

  2. 定义Man-Kendall趋势检验统计量S:

其中Sign()为符号函数,计算公式为:

  1. 时,统计量S大致服从正态分布,其均值为0,方差,标准化后得到检验统计量Z值如下:

  1. 趋势检验结果
h 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年)的月降雨量进行测试,趋势检验结果如下所示:

结果分析

后续再补充。

问题总结

  1. 样本大小

在对时间序列进行检验时,要保证样本足够大,以确保趋势检验的结果具有统计学意义。

  1. 空间差异性

当研究区较小时,对全流域进行mann-kendall趋势检验,可能会出现均呈现统一的下降或增加的趋势,则空间差异性较差,不利于结果的讨论和分析。此时则可以选择线性规划的斜率来表征数据的趋势。