MATLAB Mann-Kendall突变检验 (mk突变检验)

该博客介绍了Mann-Kendall突变检验的MATLAB实现,包括正序和逆序计算过程,用于检测时间序列中的突变点。代码经过优化和错误修正,提供了一种直观的图像解析方法,帮助识别数据序列中的变化趋势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

任务描述:对时间序列进行MK突变检验:

将MK突变检验的代码封装为函数,直接调用即可,代码如下:

%% MK突变检验
%% 修改日期 2022/7/29

function [UF,UB] = MKbreak(time_series)

n = length(time_series);

%%  ---------------------------------正序列计算--------------------------------
% 定义统计量UF,长度=n,初始值=0;
UF=zeros(size(time_series));

E = n*(n-1)/4;                         % E是累计数s(k)的均值
Var = n*(n-1)*(2*n+5)/72;              % Var是累计数s(k)的方差

% 定义秩序列,r(i)记录的是第i个时刻,其数值大于j时刻(其中j<=i)数值的个数的
for i= 1:n
    r1(i) = sum(time_series(i)>time_series(1:i));
end

% 定义累计量序列s,s(k)记录的是第i个时刻(其中i<=k),其数值大于j时刻(其中j<=i)数值个数的累计数
s = zeros(size(time_series));
% k从2开始,因为根据统计量UF(k)公式,k=1时,s(1)、E(1)、Var(1)均为0,此时UF无意义,因此公式中,令UFk(1)=0
for k = 2:n
   s(k) = sum(r1(1:k));

   E = k*(k-1)/4;                     % s(k)的均值
   Var = k*(k-1)*(2*k+5)/72;          % s(k)的方差
   UF(k) = (s(k)-E)/sqrt(Var);
end

%% ---------------------------------逆序列计算--------------------------------
% 按时间序列逆转样本,构造逆序列time_series2和
for i=1:n
    time_series2(i)=time_series(n-i+1);
end
% 定义逆序统计量UB,长度=n,初始值=0
UB = zeros(size(time_series2));
for i= 1:n
    r2(i) = sum(time_series2(i)>time_series2(1:i));
end

% 定义逆序累计量序列s2,长度=n,初始值=0
s2 = zeros(size(time_series2));
% i从2开始,因为根据统计量UB(k)公式,i=1时,s2(1)、E(1)、Var(1)均为0,此时UB无意义,因此公式中,令UB(1)=0
for k = 2:n
   s2(k) = sum(r2(1:k));
   
   E = k*(k-1)/4;                     % s2(k)的均值
   Var = k*(k-1)*(2*k+5)/72;          % s2(k)的方差
% 由于对逆序序列的累计量S2的构建中,依然用的是累加法,即后者大于前者时r加1,
% 则r的大小表征了一种上升的趋势的大小,而序列逆序以后,应当表现出与原序列相反
% 的趋势表现,因此,用累加法统计S2序列,统计量公式(S(i)-E(i))/sqrt(Var(i))
% 也不应改变,但统计量UBk应取相反数以表征正确的逆序序列的趋势
  UB(k) = -(s2(k)-E)/sqrt(Var);
end

%% ---------------------------------绘图
% 此时上一步的到UB表现的是逆序列在逆序时间上的趋势统计量
% 与UF做图寻找突变点时,2条曲线应具有同样的时间轴,因此
% 再按时间序列逆转结果统计量UB,得到时间正序的UB,做图用
for i=1:n
   UB2(i)=UB(n-i+1);
end
x = 1:n;

plot(x,UF,'g-','linewidth',1.5);
hold on
plot(x,UB2,'m-','linewidth',1.5);
% plot(x,UB,'m-','linewidth',1.5);
plot(x,1.96*ones(n,1),'-.r','linewidth',1);
plot(x,0*ones(n,1),'-','color',[0.2,0.2,0.2],'linewidth',1);
plot(x,-1.96*ones(n,1),'-.r','linewidth',1);
grid(gca,'minor')% 画出次格网

axis([min(x),max(x),-5,5]);
legend('UF统计量','UB统计量','0.05显著水平');
set(gca,'Fontsize',12)
set(gca,'ytick',-5:1:5)
xlabel('{\itt} (year)','FontSize',15);
ylabel('统计量','Fontsize',15);

end

注:代码并非全部原创,是修改自Mann-Kendall突变检测(mk突变检测),优化了部分语法,修正了部分错误,更正了部分描述。

突变检验结果如下:
在这里插入图片描述
图像解读方法如下,来自mk突变点检测_(案例)时间序列分析之MK突变检测
在这里插入图片描述
Hope this may bring you some inspirations!

在这里插入图片描述

### Matlab 突变检测代码示例 #### MK突变检验算法 MK突变检验是一种常用的统计方法,用于检测时间序列中的趋势变化。下面是一个基于MatlabMK突变检验算法程序,该程序包含了详细的注释,方便初学者理解和修改。 ```matlab function [S, p] = mk_test(x) % 输入参数 x 是待检验的时间序列向量 n = length(x); % 获取样本数量 S = 0; % 初始化秩次累加和 S for i = 1:n-1 for j = i+1:n if x(j) > x(i) S = S + 1; elseif x(j) < x(i) S = S - 1; end end end % 计算方差 Var(S) Var_S = (n*(n-1)*(2*n+5))/18; % 当 n 较大时,使用正态分布近似计算p值 if n >= 10 Z = S / sqrt(Var_S); else error('Sample size too small'); end % 双侧检验下的p值 p = 2 * (1-normcdf(abs(Z))); disp(['The test statistic is ', num2str(S)]); disp(['The corresponding p-value is ', num2str(p)]); if p < 0.05 disp('Reject null hypothesis: There exists a significant trend.') else disp('Fail to reject null hypothesis: No significant trend found.') end ``` 此段代码实现了Mann-Kendall突变检验的核心逻辑,并提供了清晰的结果输出[^1]。 #### Pettitt突变检验实战 除了上述提到的方法外,在实际应用中还经常采用Pettitt突变检验来查找单个突变点的位置。以下是具体的实现方式: ```matlab function k = pettitt_test(y) % y 表示输入的时间序列数组 N=length(y); U=zeros(N,1); W=nanmean(cumsum(repmat(sign(diff([y(:);NaN])),1,N)-repmat((1:N)',1,N))); for t=1:N-1 U(t)=abs(sum(W(1:t))-sum(W(t+1:end))); end k=find(U==max(U),1,'first'); % 找到最大绝对值得索引位置即为估计的突变年份 fprintf('Estimated change point at year index:%d\n',k); plot(1:N,y,'b-',k,y(k),'ro') legend({'Time Series','Change Point'}) xlabel('Year Index'),ylabel('Value') title('Pettitt Test Result') grid on ``` 这段脚本不仅完成了Pettitt突变点定位的任务,同时也绘制出了原始数据曲线及其推测出来的突变时刻标记图象[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值