【趋势分析方法一】MATLAB实现Mann-Kendall趋势/突变检验

非参数Mann-Kendall检验

在时间序列趋势分析中,Mann-Kendall检验是世界气象组织推荐并已被广泛使用的非参数检验方法,最初由Mann和Kendall提出,现已被很多学者用来分析降雨、气温、径流和水质等要素时间序列的趋势变化。Mann-Kendall检验不需要样本遵从一定的分布,也不受少数异常值的干扰,适用于水文、气象等非正态分布的数据,计算简便。

1 单变量M-K方法

1.1 Mann-Kendall趋势检验

【趋势分析方法一】MATLAB实现Mann-Kendall趋势/突变检验_第1张图片
【趋势分析方法一】MATLAB实现Mann-Kendall趋势/突变检验_第2张图片

1.2 Mann-Kendall突变检验

【趋势分析方法一】MATLAB实现Mann-Kendall趋势/突变检验_第3张图片

1.3 MATLAB实现代码

MATLAB调用函数代码如下:

[~ ,~ ,UFk ,UBk ]= MKTest( X ,Length );

MATLAB实现MK趋势/突变分析的函数如下:

function  [Zs ,beta ,UFk ,UBk2 ]= MKTest(Data,n)
% MKTest函数用于趋势和突变检验
% 输入参数
% Data    序列数据
% n         序列长度
% 输出参数
% Zs       统计量
% beta    斜率
% UFk     统计量UFk
% UBk2   逆序统计量

%% 趋势分析线性:Mann-Kendall检验
Sgn=zeros(n-1,n-1);        %初始化分配内存
for i=1:n-1
    for j=i+1:n
        if((Data(j)-Data(i))>0)
            Sgn(i,j)=1;
        else
            if((Data(j)-Data(i))==0)
                Sgn(i,j)=0;
            else
                if((Data(j)-Data(i))<0)
                    Sgn(i,j)=-1;
                end
            end
        end
    end
end
Smk=sum(sum(Sgn));

VarS=n*(n-1)*(2*n+5)/18;

if n>10
    if Smk>0
        Zs=(Smk-1)/sqrt(VarS);
    else
        if Smk==0
            Zs=0;
        else
            if  Smk<0
                Zs=(Smk+1)/sqrt(VarS);
            end
        end
    end
end

%% beta 斜率 描述单调趋势
t=1;
for i=2:n
   for j=1:(i-1)
       temp(t)=( Data(i)-Data(j) )/( i-j );
       t=t+1;
   end
end
beta=median( temp );

%% 突变检验
Sk=zeros(n,1);          % 定义累计量序列Sk
UFk=zeros(n,1);        % 定义统计量UFk
s = 0;
% 正序列计算start---------------------------------
for i=2:n
   for j=1:i
         if Data(i)>Data(j)
           s=s+1;
         else
           s=s+0;
         end
   end
   Sk(i)=s;
   E=i*(i-1)/4; % Sk(i)的均值
  Var=i*(i-1)*(2*i+5)/72; % Sk(i)的方差
  UFk(i)=(Sk(i)-E)/sqrt(Var);
end
% 正序列计算end---------------------------------

% 逆序列计算start---------------------------------
Sk2=zeros(n);  % 定义逆序累计量序列Sk2
UBk=zeros(n,1); 
s=0;
Data2=flipud(Data);        % 按时间序列逆转样本y
for i=2:n
   for j=1:i
         if Data2(i)>Data2(j)
           s=s+1;
         else
           s=s+0;
         end
   end
   Sk2(i)=s;
   E=i*(i-1)/4; 
  Var=i*(i-1)*(2*i+5)/72; 
  UBk(i,1)=0-(Sk2(i)-E)/sqrt(Var);
end
% 逆序列计算end------------------------------
UBk2=flipud(UBk);
UFk=UFk';
UBk2=UBk2';
%{
figure(3)%画图
plot(1:n,UFk,'r-','linewidth',1.5);
hold on
plot(1:n,UBk2,'b-.','linewidth',1.5);
plot(1:n,1.96*ones(n,1),':','linewidth',1);
% axis([1,n,-5,8]);
legend('UF统计量','UB统计量','0.05显著水平');
xlabel('t (year)','FontName','TimesNewRoman','FontSize',12);
ylabel('统计量','FontName','TimesNewRoman','Fontsize',12);
%grid on
hold on
plot(1:n,0*ones(n,1),'-.','linewidth',1);
plot(1:n,1.96*ones(n,1),':','linewidth',1);
plot(1:n,-1.96*ones(n,1),':','linewidth',1);
%}
end

根据计算结果绘图代码如下(仅举一子图为例):

subplot(4,1,4);
plot(1:Length_year,UFk_year{1,1}(4,:),'b-','linewidth',1.5);
hold on
plot(1:Length_year,UBk_year{1,1}(4,:),'b:','linewidth',1.5);
axis([1 Length_year -4 4]);
xlabel('Year','FontName','TimesNewRoman','FontSize',10);
ylabel( 'SRI_1_2' ,'FontName','TimesNewRoman','FontSize',10);
plot(1:Length_year,1.96*ones(Length_year,1),'-b','linewidth',0.1);
plot(1:Length_year,-1.96*ones(Length_year,1),'-b','linewidth',0.1);
set(gca, 'XTick', [2 :5 : 57],'XTickLabel',{'1955','1960','1965','1970','1975','1980','1985','1990','1995','2000','2005','2010'}) ;

图形如下所示:
【趋势分析方法一】MATLAB实现Mann-Kendall趋势/突变检验_第4张图片

2 多变量M-K方法

2.1 原理

2.2 MATLAB实现代码

3 参考

3.1 论文参考

1.参考文献:J1998-A modified Mann-Kendall trend test for autocorrelated data(论文下载地址)
2.参考文献:J2002-The influence of autocorrelation on the ability to detect trend in hydrological series(论文下载地址)
3.参考文献:J2013-The modified Mann-Kendall test: on the performance of three variance correction approaches(论文下载地址)

3.2 其它语言实现MK分析

1.Python
Mann-Kendall趋势分析

你可能感兴趣的:(#,MATLAB实现各种基础方法,matlab)