Sen+MK长时间序列趋势性分析----基于python的代码实现

sen+mk python实现代码免费共享-----赶紧收藏吧

python开源社区公布了进行sen+mk趋势性检验的官方包,有关该官方包的主要内容详见:https://github.com/Coder2cdb/pyMannKendall,开源不易,有些人还收费查看,我觉得没必要,本次代码免费分享给大家,有需要的收藏点赞!

本次sen+mk python代码输入参数:多年影像的存储路径
path1=r"E:\2021-03-03—生态修复\吴起本地\NDVI_wuqi"
本次sen+mk python代码输出参数:结果影像存储路径
result_path=r"E:\生态修复\1990-2000_NDVI\result"
调用方法:
sen_mk_test(path1, result_path)
MannKendall输出参数说明

''       
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
        Tau: Kendall Tau
        s: Mann-Kendal's score
        var_s: Variance S
        slope: Theil-Sen estimator/slope
        intercept: intercept of Kendall-Theil Robust Line
'''

1.导入python包

#coding:utf-8
import numpy as np
import pymannkendall as mk
import os 
import rasterio as ras

2.获取所有的影像路径,按照从小到大年份排序

path1=r"E:\2021-03-03—生态修复\吴起本地\NDVI_wuqi"
filepaths=[]
for file in os.listdir(path1):
    filepath1=os.path.join(path1,file)
    filepaths.append(filepath1)

3.读取所有的影像数据并拼接为一个numpy矩阵

#获取影像数量
num_images=len(filepaths)
#读取影像数据
img1=ras.open(filepaths[0])
#获取影像的投影,高度和宽度
transform1=img1.transform
height1=img1.height
width1=img1.width 
array1=img1.read()
img1.close()

#读取所有影像
for path1 in filepaths[1:]:
    if path1[-3:]=='tif':
        print(path1)
        img2=ras.open(path1)
        array2=img2.read()
        array1=np.vstack((array1,array2))
        img2.close()
    
nums,width,height=array1.shape

4.定义输出矩阵

#输出矩阵,无值区用-9999填充    
slope_array=np.full([width,height],-9999.0000) 
z_array=np.full([width,height],-9999.0000)
Trend_array=np.full([width,height],-9999.0000) 
Tau_array=np.full([width,height],-9999.0000)
s_array=np.full([width,height],-9999.0000)
p_array=np.full([width,height],-9999.0000)
#只有有值的区域才进行mk检验,如果所有影像同一像元都为空,则不进行mk检验
c1=np.isnan(array1)
sum_array1=np.sum(c1,axis=0)
nan_positions=np.where(sum_array1==num_images)
positions=np.where(sum_array1!=num_images) 
#输出总像元数量
print("all the pixel counts are {0}".format(len(positions[0])))

5.sen+mk检验

for i in range(len(positions[0])):
    print(i)
    x=positions[0][i]
    y=positions[1][i]    
    mk_list1=array1[:,x,y]
    trend, h, p, z, Tau, s, var_s, slope, intercept  = mk.original_test(mk_list1)
    if trend=="decreasing":
        trend_value=-1
    elif trend=="increasing":
        trend_value=1
    else:
        trend_value=0
    slope_array[x,y]=slope#senslope
    s_array[x,y]=s
    z_array[x,y]=z
    Trend_array[x,y]=trend_value
    p_array[x,y]=p
    Tau_array[x,y]=Tau

6.定义写影像的函数

#写影像,包括宽度,高度,投影,波段名,矩阵
def writeImage(image_save_path,height1,width1,para_array,bandDes,transform1):
    with ras.open(
           image_save_path,
           'w',
           driver='GTiff',
           height=height1,
           width=width1,
           count=1,
           dtype=para_array.dtype,
           crs='+proj=latlong',
           transform=transform1,
    ) as dst:
               dst.write_band(1,para_array)
               dst.set_band_description(1,bandDes)
    del dst

7.输出结果

#输出矩阵
all_array=[slope_array,Trend_array,p_array,s_array,Tau_array,z_array]   
#输出路径
result_path=r"E:\2021-03-03—生态修复\吴起本地\result"
slope_save_path=os.path.join(result_path,"slope.tif")
Trend_save_path=os.path.join(result_path,"Trend.tif")
p_save_path=os.path.join(result_path,"p.tif")
s_save_path=os.path.join(result_path,"s.tif")
tau_save_path=os.path.join(result_path,"tau.tif")
z_save_path=os.path.join(result_path,"z.tif")
image_save_paths=[slope_save_path,Trend_save_path,p_save_path,s_save_path,tau_save_path,z_save_path]
band_Des=['slope','trend','p_value','score','tau','z_value']
#逐个存储
for i in range(len(all_array)):
    writeImage(image_save_paths[i], height1, width1, all_array[i], band_Des[i],transform1)

sen+mk代码汇总

'''
Created on 2021年4月11日

@author: SunStrong
'''
#coding:utf-8
import numpy as np
import pymannkendall as mk
import os 
import rasterio as ras



def sen_mk_test(image_path,outputPath):
    
    #image_path:影像的存储路径
    #outputPath:结果输出路径
    
    filepaths=[]
    for file in os.listdir(path1):
        filepath1=os.path.join(path1,file)
        filepaths.append(filepath1)
    
    #获取影像数量
    num_images=len(filepaths)
    #读取影像数据
    img1=ras.open(filepaths[0])
    #获取影像的投影,高度和宽度
    transform1=img1.transform
    height1=img1.height
    width1=img1.width 
    array1=img1.read()
    img1.close()
    
    #读取所有影像
    for path1 in filepaths[1:]:
        if path1[-3:]=='tif':
            print(path1)
            img2=ras.open(path1)
            array2=img2.read()
            array1=np.vstack((array1,array2))
            img2.close()
        
    nums,width,height=array1.shape 
    #写影像
    def writeImage(image_save_path,height1,width1,para_array,bandDes,transform1):
        with ras.open(
               image_save_path,
               'w',
               driver='GTiff',
               height=height1,
               width=width1,
               count=1,
               dtype=para_array.dtype,
               crs='+proj=latlong',
               transform=transform1,
        ) as dst:
                   dst.write_band(1,para_array)
                   dst.set_band_description(1,bandDes)
        del dst
    
    #输出矩阵,无值区用-9999填充    
    slope_array=np.full([width,height],-9999.0000) 
    z_array=np.full([width,height],-9999.0000)
    Trend_array=np.full([width,height],-9999.0000) 
    Tau_array=np.full([width,height],-9999.0000)
    s_array=np.full([width,height],-9999.0000)
    p_array=np.full([width,height],-9999.0000)
    #只有有值的区域才进行mk检验
    c1=np.isnan(array1)
    sum_array1=np.sum(c1,axis=0)
    nan_positions=np.where(sum_array1==num_images)
    
    positions=np.where(sum_array1!=num_images) 
    
    
    #输出总像元数量
    print("all the pixel counts are {0}".format(len(positions[0])))
    #mk test
    for i in range(len(positions[0])):
        print(i)
        x=positions[0][i]
        y=positions[1][i]    
        mk_list1=array1[:,x,y]
        trend, h, p, z, Tau, s, var_s, slope, intercept  = mk.original_test(mk_list1)
        '''        
        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
                Tau: Kendall Tau
                s: Mann-Kendal's score
                var_s: Variance S
                slope: Theil-Sen estimator/slope
                intercept: intercept of Kendall-Theil Robust Line
        '''
        
        
        if trend=="decreasing":
            trend_value=-1
        elif trend=="increasing":
            trend_value=1
        else:
            trend_value=0
        slope_array[x,y]=slope#senslope
        s_array[x,y]=s
        z_array[x,y]=z
        Trend_array[x,y]=trend_value
        p_array[x,y]=p
        Tau_array[x,y]=Tau 
        
        
    all_array=[slope_array,Trend_array,p_array,s_array,Tau_array,z_array]   
    
    slope_save_path=os.path.join(result_path,"slope.tif")
    Trend_save_path=os.path.join(result_path,"Trend.tif")
    p_save_path=os.path.join(result_path,"p.tif")
    s_save_path=os.path.join(result_path,"s.tif")
    tau_save_path=os.path.join(result_path,"tau.tif")
    z_save_path=os.path.join(result_path,"z.tif")
    image_save_paths=[slope_save_path,Trend_save_path,p_save_path,s_save_path,tau_save_path,z_save_path]
    band_Des=['slope','trend','p_value','score','tau','z_value']
    for i in range(len(all_array)):
        writeImage(image_save_paths[i], height1, width1, all_array[i], band_Des[i],transform1)

#调用
path1=r"E:\2021-03-03—生态修复\吴起本地\NDVI_wuqi"
result_path=r"E:\2021-03-03—生态修复\吴起本地\result"
sen_mk_test(path1, result_path)





在Matlab中,可以使用Sen+MK检验来检测时间序列数据中的趋势性Sen+MK检验是一种非参数的统计检验方法,适用于时间序列数据的线性和非线性趋势的检测。 以下是基于Matlab的Sen+MK趋势性检验步骤: 1. 导入数据:使用Matlab中的“xlsread”函数或其他适当的函数,将时间栅格数据导入到Matlab中。 2. 计算排名:对于每个时间点,计算数据排名。 3. 计算Sen斜率:对于每个时间点,计算数据的Sen斜率。 4. 计算MK统计量:计算MK统计量来检测趋势的显著性。 5. 计算p值:使用MK统计量计算p值。 6. 判断趋势显著性:通过比较p值与显著性水平(通常为0.05或0.01),来判断趋势是否显著。 以下是一个简单的Matlab代码示例,用于执行Sen+MK趋势性检验: ```matlab % 导入数据 data = xlsread('data.xlsx'); % 计算排名 rank_data = tiedrank(data); % 计算Sen斜率 n = length(data); sen_slope = zeros(n, 1); for i = 1:n for j = i+1:n sen_slope(i) = sen_slope(i) + sign(data(j)-data(i)); end end sen_slope = sen_slope ./ nchoosek(n, 2); % 计算MK统计量 mk_statistic = sum(sen_slope); % 计算p值 var_sen_slope = sum((sen_slope-mk_statistic).^2) / (n*(n-1)*(2*n+5)); z = (mk_statistic-1) / sqrt(var_sen_slope); p_value = 2 * (1-normcdf(abs(z))); % 判断趋势显著性 if p_value < 0.05 disp('The trend is significant.'); else disp('The trend is not significant.'); end ``` 以上代码可用于计算一个含有n个数据点的时间序列Sen+MK趋势性检验
评论 70
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值