【森气杂谈】python利用pymannkendall包进行MK(Mann-Kendall)趋势检验

【森气杂谈】python利用pymannkendall包进行MK(Mann-Kendall)趋势检验

气象学中常用的Mann-Kendall趋势检验,是一种非参数统计检验方法。该方法可用于分析中心趋势不稳定的时间序列,基于数据的秩,而不是数据本身。Mann-Kendall趋势检验适用于分析持续增长或下降趋势(单调趋势)的时间序列数据。适用于所有的分布(即数据不需要满足正态分布的假设),但数据应该没有序列相关性。如果数据具有序列相关性,则会在显著性水平(p值)上产生影响。
更进一步的原理和公式可以参考这个博客
今天要介绍的是一个python第三方包----pymannkendall,该包集成了MK(Mann-Kendall)趋势检验,而不需要自己写公式定义函数。

安装pymannkendall

首先需要安装pymannkendall

平台方法
Windowspip install pymannkendall
condaconda install -c conda-forge pymannkendall
Linuxsudo pip install pymannkendall

实例----普通MK趋势检验

调用pymannkendall

# -*- encoding: utf-8 -*-
'''
@File    :   mk_demo.py
@Time    :   2021/11/27 12:01:23
@Author  :   HMX 
@Version :   1.0
@Contact :   kzdhb8023@163.com
'''
# here put the import lib
import pymannkendall as mk
import numpy as np

# 生成3组数据
data = np.random.random(100)
data2 = np.arange(100)
data3 = np.arange(100,0,-1)

for x in [data,data2,data3]:
    result = mk.original_test(x,alpha=0.05)#alpha默认为0.05
    print(result)
    

结果

Mann_Kendall_Test(trend='no trend', h=False, p=0.823256299016955, z=-0.22335875907380243, Tau=-0.015353535353535354, s=-76.0, var_s=112750.0, slope=-0.0002038833935962383, intercept=0.4745895001589582)
Mann_Kendall_Test(trend='increasing', h=True, p=0.0, z=14.73869998208331, Tau=1.0, s=4950.0, var_s=112750.0, slope=1.0, intercept=0.0)
Mann_Kendall_Test(trend='decreasing', h=True, p=0.0, z=-14.73869998208331, Tau=-1.0, s=-4950.0, var_s=112750.0, slope=-1.0, intercept=100.0)

当然我们也可以直接print我们需要的参数即可。

print(f'trend:{res.trend}','p_value:{:.2f}'.format(res.p),'slope:{:.2f}'.format(res.slope),sep = ',')
trend:no trend,p_value:0.74,slope:0.00
trend:increasing,p_value:0.00,slope:1.00
trend:decreasing,p_value:0.00,slope:-1.00

除了普通的mk趋势检验外,针对空间条件开发了其他几种修正的Mann-Kendall检验,如多元MK检验、区域MK检验、相关MK检验、部分MK检验等。具体请参考pymannkendall官方文档

自定义的mk趋势检验函数

这边是我参考这篇博客修改后添加了趋势拟合后的代码

# -*- encoding: utf-8 -*-
'''
@File    :   mk_trend.py
@Time    :   2021/08/15 20:31:49
@Author  :   HMX 
@Version :   1.0
@Contact :   kzdhb8023@163.com
'''

# here put the import lib
from scipy.stats import norm
import numpy as np
from sklearn.linear_model import LinearRegression
 
 
def mk(x, alpha=0.1):
    n = len(x)

    # 计算趋势slope
    model = LinearRegression()
    model.fit(np.arange(1,n+1).reshape(-1,1),x)
    slope = model.coef_[0]
 
    # 计算S的值
    s = 0
    for j in range(n - 1):
        for i in range(j + 1, n):
            s += np.sign(x[i] - x[j])
 
    # 判断x里面是否存在重复的数,输出唯一数队列unique_x,重复数数量队列tp
    unique_x, tp = np.unique(x, return_counts=True)
    g = len(unique_x)
 
    # 计算方差VAR(S)
    if n == g:  # 如果不存在重复点
        var_s = (n * (n - 1) * (2 * n + 5)) / 18
    else:
        var_s = (n * (n - 1) * (2 * n + 5) - np.sum(tp * (tp - 1) * (2 * tp + 5))) / 18
 
    # 计算z_value
    if n <= 10:  # n<=10属于特例
        z = s / (n * (n - 1) / 2)
    else:
        if s > 0:
            z = (s - 1) / np.sqrt(var_s)
        elif s < 0:
            z = (s + 1) / np.sqrt(var_s)
        else:
            z = 0
 
    # 计算p_value,可以选择性先对p_value进行验证
    p = 2 * (1 - norm.cdf(abs(z)))
 
    # 计算Z(1-alpha/2)
    h = abs(z) > norm.ppf(1 - alpha / 2)
 
    # 趋势判断
    if (z < 0) and h:
        trend = -1#'decreasing'
    elif (z > 0) and h:
        trend = 1#'increasing'
    else:
        trend = 0#'no trend'
 
    return trend,p,slope


if __name__ == '__main__':
    data = np.random.random(100)
    data2 = np.arange(100)
    data3 = np.arange(100,0,-1)
    for x in [data,data2,data3]:
        trend,p,slope = mk(x,alpha = 0.05)
        print(f'trend:{trend}','p_value:{:.2f}'.format(p),'slope:{:.2f}'.format(slope),sep = ',')

结果

trend:0,p_value:0.23,slope:0.00
trend:1,p_value:0.00,slope:1.00
trend:-1,p_value:0.00,slope:-1.00

对比之下可以发现利用pymannkendall,MK趋势检验更简单方便。

参考文献

趋势检验方法(二)MK趋势检验
Mann-Kendall’ test 曼-肯德尔趋势检验法
《现在气候统计诊断与预测技术(第2版)魏凤英编》

  • 16
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: mann-kendall趋势检验是一种常用的非参数统计方法,用于检验时间序列数据中是否存在趋势。在Python中,可以使用scipy库中的mann kendall函数进行mann-kendall趋势检验。该函数的使用方法如下: from scipy.stats import kendalltau tau, p_value = kendalltau(x) 其中,x为待检验的时间序列数据,tau为kendall tau系数,p_value为p值。如果p值小于显著性水平(通常为0.05),则可以拒绝原假设,即认为存在趋势。 ### 回答2: Mann-Kendall趋势检验是一种常见的非参数统计方法,用于检测时间序列数据中的趋势性。它可以帮助我们确定数据中是否存在单调递增或递减的趋势性。Mann-Kendall趋势检验最适用于具有连续性和单调性的数据,例如气象数据、水文数据和经济数据等。 使用Python进行Mann-Kendall趋势检验非常方便,我们可以使用SciPy库中的“stats”模块来实现。首先,我们需要导入必要的库: ```python import numpy as np from scipy.stats import kendalltau from scipy.stats import norm ``` 然后,我们需要定义一个函数来计算Mann-Kendall趋势检验的p值: ```python def mk_test(x, alpha=0.05): """ Perform the Mann-Kendall test for trend in a time series. Parameters ---------- x : list or numpy array The time series to test for trend. alpha : float, optional The significance level for the test. Returns ------- trend : int The direction of the trend (-1 for a decreasing trend, 0 for no trend, 1 for an increasing trend). pvalue : float The p-value for the test. """ n = len(x) s = [0] * n for k in range(n - 1): for j in range(k + 1, n): s[k] += np.sign(x[j] - x[k]) sgn = np.sign(s) if sum(sgn) == 0: trend = 0 elif np.all(sgn == 1): trend = 1 elif np.all(sgn == -1): trend = -1 else: trend = 0 var_s = (n * (n - 1) * (2 * n + 5)) / 18 std_dev = np.sqrt(var_s) if s[0] == 0: z = 0 else: z = (s[0] - 1) / std_dev p = 2 * norm.sf(abs(z)) if p <= alpha: h = True else: h = False return trend, p ``` 在这个函数中,“x”参数表示要进行趋势检验的时间序列数据,“alpha”参数表示设置的显著性水平。函数将返回一个元组,“trend”表示数据的趋势方向(-1表示递减趋势,0表示无趋势,1表示递增趋势),“pvalue”表示Mann-Kendall趋势检验的p值。如果p值小于或等于设置的显著性水平,则说明存在趋势性。 下面是一个示例代码,它使用上述函数来测试一个气温时间序列数据是否存在趋势性。首先,我们从CSV文件中读取气温数据: ```python import pandas as pd data = pd.read_csv("temperature.csv") x = data["Temperature"].values ``` 然后,我们使用定义好的mk_test函数进行趋势检验: ```python trend, p = mk_test(x) if trend == -1: print("The temperature is decreasing over time.") elif trend == 0: print("There is no significant trend in the temperature.") else: print("The temperature is increasing over time.") if p <= 0.05: print("The trend is significant at the 5% level.") else: print("The trend is not significant at the 5% level.") ``` 这个代码将输出检验结果,如果气温存在显著的单调递增或递减趋势,则表示存在显著的变化。如果p值小于等于0.05,则表示趋势显著。这表明,使用Python实现Mann-Kendall趋势检验是非常简单和有效的。 ### 回答3: mann-kendall趋势检验是一种非参数检验方法,用于检测时间序列数据中是否存在趋势性。其基本原理是通过计算每个数据点和其后继数据点之间的差异,然后比较其正负性来确定趋势的方向。在Python中,我们可以使用scipy库中的mannkendall函数来进行mann-kendall趋势检验。 使用mannkendall函数需要传入一个一维时间序列数组,然后返回两个值:趋势检验统计量(Mann-Kendall test statistic)和P值。P值表示检验结果的显著性程度,一般取0.05或0.01作为判断标准。如果P值小于0.05或0.01,则拒绝原假设,认为时间序列数据存在趋势性。 我们可以使用下面的代码来演示如何在Python中使用mannkendall函数进行趋势检验: ```python from scipy.stats import mannkendall # 生成一个随机时间序列 import random ts = [random.randint(0, 10) for i in range(100)] # 进行趋势检验 result, p_value = mannkendall(ts) # 输出结果 print("mann-kendall test statistic:", result) print("p-value:", p_value) ``` 上述代码中,首先使用Python的random模块生成一个随机时间序列,然后调用mannkendall函数进行趋势检验。最后输出检验结果。如果P值小于0.05或0.01,则可以认为时间序列数据中存在趋势性,否则就可以认为时间序列数据中没有趋势性。 总之,mann-kendall趋势检验是一种非常有用的方法,可以用于检测时间序列数据中的趋势性,Python中的mannkendall函数可以方便地进行调用和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值