第一次接触气象干旱综合指数MCI时,我也被这个专业名词唬住了。简单来说,MCI就像是一个"干旱体检报告",它能综合反映一个地区在不同时间尺度上的干旱状况。这个指数特别适合农业领域,因为农作物从播种到收获,每个生长阶段对水分的需求都不一样。
MCI的计算公式看起来复杂,但其实原理很直观:它综合了四个关键指标(SPIW60、MI30、SPI90、SPI150),每个指标反映不同时间尺度的水分状况。就像医生看体检报告时会重点关注某些指标一样,MCI也会根据不同地区(南方/北方)和不同季节,给这些指标分配不同的权重。
MCI的计算公式是这样的:
code复制MCI = Ka * (a*SPIW60 + b*MI30 + c*SPI90 +d*SPI150)
这个公式里有几个关键点需要注意:
权重系数:a、b、c、d这四个系数会根据地区不同而变化。比如北方地区通常取a=0.3,b=0.5,c=0.3,d=0.2;而南方地区则是a=0.55,b=0.6,c=0.2,d=0.1。这种差异反映了南北气候特点的不同。
季节调节系数Ka:这个系数特别重要,它根据农作物生长阶段对水分的敏感程度而变化。比如在作物需水关键期(通常是春夏季节),Ka值会调高(1.0-1.2),而在其他时期则会降低(0.4-0.8)。
四个核心指标:
在实际计算MCI之前,我们需要做好数据准备工作。以三门峡地区的数据为例,原始数据通常包含以下字段:
在MATLAB中,我们首先需要清理数据,比如处理闰年2月29日的数据:
matlab复制data = xlsread('三门峡1957.1.1-2021.3.1.xlsx');
data(any((data(:,3)*100+data(:,4)==229),2),:)=[];
P = data(:,5); % 提取降水量数据
这一步很关键,因为闰日的数据会影响后续的时间序列计算。我在实际项目中就遇到过因为没处理闰日数据导致计算结果出现周期性异常的情况。
SPIW60的计算相对复杂一些,它采用了加权平均的方法,越近的降水数据权重越大:
matlab复制a=0.85; % 衰减系数
N=60; % 60天窗口
omega=zeros(N+1,1);
for n=0:N
omega(n+1)= a^n; % 计算权重
end
ndays=length(P) - N;
WAP=zeros(ndays,1);
for idays=1:ndays
for n=0:N
WAP(idays,1)=WAP(idays,1)+omega(n+1)*P(idays+N-n);
end
end
这里有个小技巧:因为前60天的数据不足以计算完整的60天加权平均,所以通常我们会舍弃第一年的数据,从第二年开始计算。
SPI90和SPI150的计算方法类似,都是计算指定时间窗口内的累计降水量,然后进行标准化处理:
matlab复制% SPI90计算
scale90=90;
P90 = zeros(length(P)-scale90+1,1);
for j=1:length(P90)
P90(j+scale90-1)=sum(P(j:j+scale90-1));
end
P90=P90(366:end,1); % 舍弃第一年数据
% SPI150计算
scale150=150;
P150 = zeros(length(P)-scale150+1,1);
for j=1:length(P150)
P150(j+scale150-1)=sum(P(j:j+scale150-1));
end
P150=P150(366:end,1);
标准化处理时,我们需要考虑降水量为零的情况:
matlab复制[zeroa]=find(Xn==0); % 找到降水量为零的位置
Xn_nozero=Xn;
Xn_nozero(zeroa)=[];
q=length(zeroa)/length(Xn);
parm=gamfit(Xn_nozero); % 拟合Gamma分布
Gam_xs=q+(1-q)*gamcdf(Xn,parm(1),parm(2));
SPI90(tind)=norminv(Gam_xs); % 转换为标准正态分布
MI30(水分盈亏指数)的计算需要先计算潜在蒸散发量(PET),这部分比较复杂:
matlab复制% 计算潜在蒸散发量E0
ELE = data(1,14); % 海拔高度
LAT = data(1,13); % 纬度
Tmean = data(:,7); % 平均温度
Ws = data(:,10); % 风速
Hum = data(:,11); % 湿度
Sun = data(:,12); % 日照时数
% 一系列气象参数计算
delta=4098*0.6108*exp(17.27*Tmean./(Tmean+237.3))./(Tmean+237.3).^2;
eS=0.6108*exp(17.27*Tmean./(Tmean+237.3));
eA=eS.*Hum/100;
gamma1 = 0.665/10^3 *Pre/10;
Phi=LAT*pi/180;
Delt=0.408*sin(2*pi*J/365-1.39);
ws=acos(-tan(Phi)*tan(Delt));
dr=1+0.033*cos(2*pi*J/365);
Gsc=0.0820;
Ra=((24*60)/pi)*Gsc*dr.*(ws.*sin(Phi).*sin(Delt)+cos(Phi).*cos(Delt).*sin(ws));
Rso=(as+bs+2*ELE/100000).*Ra;
N=24*ws/pi;
Rs=(as+bs*(Sun./N)).*Ra;
alpha=0.23;
Rns=(1-alpha)*Rs;
Tkmax=Tmean+273.16;Tkmin=Tmean+273.16;
fcd=1.35*Rs./Rso-0.35;
Rnl=(4.903*10^(-9))*fcd.*(0.34-0.14*sqrt(eA)).*((Tkmax.^4+Tkmin.^4)/2);
Rn=Rns-Rnl;
E0=(0.408.*delta.*Rn+gamma1*900./(Tmean+273).*u2.*(eS-eA))./(delta+gamma1.*(1+0.34*u2));
有了E0后,就可以计算MI30了:
matlab复制scale30=30;
P30 = zeros(length(P)-scale30+1,1);
E30 = zeros(length(P)-scale30+1,1);
for j=1:length(P30)
P30(j+scale30-1)=sum(P(j:j+scale30-1));
E30(j+scale30-1)=sum(E0(j:j+scale30-1));
end
MI30 = (P30-E30)./E30;
MI30 = MI30(366:end,1);
有了各个分量指标后,就可以计算最终的MCI指数了:
matlab复制MCI0 = a*SWAP + b*MI30 + c*SPI90 +d*SPI150;
MCI0 = [M(366:end) Ri(366:end) MCI0];
% 应用季节调节系数
X = find(MCI0(:,1)==1);MCI(X,1)=Ka(1)*MCI0(X,3);
X = find(MCI0(:,1)==2);MCI(X,1)=Ka(2)*MCI0(X,3);
...
X = find(MCI0(:,1)==12);MCI(X,1)=Ka(12)*MCI0(X,3);
MCI = [data(366:end,2:4),MCI];
这里需要注意季节调节系数的应用方式。Ka是一个包含12个元素的数组,对应1-12月。我们根据计算日期的月份,选择对应的Ka值进行调节。
在实际应用中,我发现有几个地方特别容易出错:
数据质量控制:原始气象数据中经常会有异常值或缺失值。建议在计算前先进行数据质量检查,比如检查降水量是否为负值,温度是否在合理范围内等。
时间对齐问题:由于各个指标的计算窗口不同(60天、90天、150天等),最终得到的MCI结果的时间范围也会不同。要特别注意时间戳的对应关系。
参数本地化:公式中的权重系数a、b、c、d和季节调节系数Ka需要根据当地实际情况进行调整。建议先用历史数据进行验证,看看计算结果是否符合当地的实际干旱情况。
计算效率优化:当处理长时间序列数据时(比如几十年的日数据),直接使用循环计算会非常耗时。可以考虑使用向量化运算或者并行计算来提高效率。
计算得到MCI值后,我们通常需要进行结果分析和可视化。MCI值的分级标准一般是:
在MATLAB中,我们可以用以下代码绘制干旱演变图:
matlab复制dates = datetime(data(366:end,2),data(366:end,3),data(366:end,4));
plot(dates,MCI(:,1));
hold on;
yline(-0.5,'--g');
yline(-1.0,'--y');
yline(-1.5,'--m');
yline(-2.0,'--r');
xlabel('日期');
ylabel('MCI指数');
title('干旱演变过程');
legend('MCI','无旱阈值','轻旱阈值','中旱阈值','重旱阈值');
这样的可视化结果可以帮助我们直观地了解干旱的发生、发展和缓解过程。