- 积分
- 2001
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2012-12-5
- 最后登录
- 1970-1-1
|
楼主 |
发表于 2021-8-9 11:08:05
|
显示全部楼层
对上述Mann-Kendall突变检测程序进行了优化,使得它能在屏幕直接输出准确的突变时间点。建议大家使用下面的程序:
------------------------------------------------------------------------------------------------------------
function [t0,UF,UB2]=MK(t,X,Alpha)
% Mann-Kendall 突变检测
% 输入量
% t:时间序列对应的年份
% X:时间序列,1*N维或N*1维矩阵
% Alpha: 显著水平,默认值为0.05
% 输出量
% t0:突变时间点
% UF: UF统计量,1*N维矩阵
% UB2: UB统计量序列,1*N维矩阵
if (nargin<3)||(isempty(Alpha)), Alpha=0.05;end
N=length(X);
% 正序列计算
UF=zeros(1,N); % 时间序列X的UF统计量
Sk=zeros(1,N); % 时间序列X的秩序列(累计量序列)
r=0;
for i=2:N
for j=1:i-1
%原文误写为X(i)>=X(j),得出突变点在1920年左右,并不正确
if X(i)>X(j)
r=r+1;
else
r=r+0;
end
end
Sk(i)=r;
% 原文公式错写为 ESk = i*(i+1)/4;
ESk=i*(i-1)/4;
VarSk=i*(i-1)*(2*i+5)/72;
UF(i)=(Sk(i)-ESk)/sqrt(VarSk);
end
% 逆序列计算
Y=X(N:-1:1); % 取时间序列X的逆序
UB=zeros(1,N); % 时间序列X的UB统计量
Sk2=zeros(1,N); % 时间序列Y的秩序
r=0;
for i=2:N
for j=1:i-1
%原文误写为Y(i)>=Y(j),得出突变点在1920年左右,并不正确
if Y(i)>Y(j)
r=r+1;
else
r=r+0;
end
end
Sk2(i)=r;
% 原文公式错写为 ESk = i*(i+1)/4;
ESk=i*(i-1)/4;
VarSk=i*(i-1)*(2*i+5)/72;
UB(i)=0-(Sk2(i)-ESk)/sqrt(VarSk);
end
% UB是逆序列在逆序时间上的趋势统计量
% 与UF作图寻找突变点时,2条曲线应具有同样的时间轴
% 故再按时间序列逆转UB,得到时间正序的UB2,作图用
UB2=UB(N:-1:1);
% U_Alpha是显著水平Alpha下的正态分位数,alpha=0.05时,U_Alpha=1.96
% 若UF > U_Alpha, 表明序列存在明显的趋势变化
U_Alpha=norminv(1-Alpha/2);
%寻找正序列与逆序列交叉点对应的年份
FB=abs(UF-UB2);
index=find(FB==min(FB));
t0=t(index);
figure
h1=plot(t,UF,'r-','linewidth',1);
hold on
h2=plot(t,UB2,'b-','linewidth',1);
xlabel('time')
ylabel('统计量')
hold on
h3=plot(t,U_Alpha*ones(1,N),':','color',[1 0.6 0.3],'linewidth',1.5);
plot(t,-U_Alpha*ones(1,N),':','color',[1 0.6 0.3],'linewidth',1.5)
plot(t,zeros(1,N),'-','linewidth',1)
legend([h1 h2 h3],{'UF统计量','UB统计量','0.05显著水平'},'location','best')
YY=get(gca,'Ylim');
axis([min(t) max(t) -max(abs(YY)) max(abs(YY))])
grid on
end
----------------------------------------------------------------------------------------------------------
在MATLAB中新建脚本,粘贴上述程序,保存为MK.m文件,设置路径,即可直接调用函数MK(t,X)检测突变点
|
|