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