用EOF分解16年东海月平均海表面温度

作业记录
题目:利用16年东海或南海月平均海表面温度,对该海区的海温资料进行经验正交函数分解

解答:
一、EOF(经验正交函数)分解方法的原理及分解步骤
1.EOF分析原理
气象要素场的经验正交函数分解,是将X 分解为空间函数V 和时间函数Z 两部分,即:
X = VZ
将某一气候要素场的观测资料以矩阵形式给出
在这里插入图片描述
其中m 是空间点(网格点),n 是时间点或样本数。则V可以写成
在这里插入图片描述
vi(i=1, 2…m) 表示第i 个典型场,它仅仅是空间的函数。Z 可以写成
在这里插入图片描述
Z的第i行,即为第i 个典型场所对应的时间权重系数,表征典型场随时间的演变特征。
我们将X = VZ两边同乘他们的逆矩阵,可以得到
在这里插入图片描述
令A=XXT,Λ=ZZT,则上式可以表示为
在这里插入图片描述
由主成分分析可知,其中V 的列就是矩阵A的特征向量,Λ 是A 的特征值组成的对角矩阵。
当V 求出来以后,利用下式,求出Z
在这里插入图片描述
分解工作到此完成。

2.EOF分解计算步骤
(1)根据分析目的,确定X的具体形态(原始、距平或标准化);
(2)由X求矩阵A=XX^T;
(3)求A的全部特征值λ_h,特征向量V_h,h是非零特征值的个数;
(4)将特征值作非升序排列,并对特征向量序数作相应变动;
(5)由X及主要的V_p,求其时间序数Z_n,主要的个数(典型场)由分析目的及分析对象决定;
(6)计算每个特征向量的方差贡献,以及前P个特征向量的累积方差贡献;
(7)显著性检验;
(8)输出计算结果。

二、程序实现
利用2001年~2016年16年的东海月平均海表面温度数据,对其进行EOF分析。

  1. 代码如下:
close all;clc; clear;
%--------读取数据与数据区域的选择-------%
ncdisp('D:\studentYJ\数据处理与分析\编程作业\EOF分析\monthmeansst3.nc')
ncfile='D:\studentYJ\数据处理与分析\编程作业\EOF分析\monthmeansst3.nc';
lon=ncread(ncfile,'longitude');
lat=ncread(ncfile,'latitude');
time=ncread(ncfile,'time');
SST=ncread(ncfile,'sst'); 
[lat,lon]=meshgrid(lat,lon);
m_proj('miller','long',[115,135],'lat',[20,35]);%选取研究地点:东海海域20-35°N,125-135°E
SST=SST-273;%由华氏温度转化为摄氏温度

m_pcolor(lon,lat,mean(SST,3));
m_grid('tickdir','out');
m_gshhs_l('patch',[0.8 0.8 0.8],'Edgecolor','none');
colorbar;
colormap(jet);
title('2001年~2016年东海月平均海表温度原始图');


%----------经验正交模态分解(EOF)----------%
X=[];
for i=1:size(SST,3)
X(:,i)=reshape(SST(:,:,i),size(SST,1)*size(SST,2),1);
end

%距平
X1=X(find(~isnan(X)));%找出数据中的非零值
X2=reshape(X1,length(X1)/size(SST,3),size(SST,3));
 Xba=mean(mean(X2));
 X3=X2-Xba;
 
%--------------EOF1---------------%
SST_A=1/size(SST,3)*(X3*X3');%实对称矩SST_A
[SST_V,namta]=eig(SST_A);%实对称矩SST_A的特征向量SST_V和特征值namta
val1=flipud(diag(namta));
vec1=SST_V(:,size(SST_V,1));
EOF1=vec1;%最大特征值对应特征向量即为第一EOF模态(空间函数)
EOF1=EOF1*sqrt(val1(1,1));
PC1=vec1'*X3;%%%时间函数
PC1=PC1/sqrt(val1(1,1));
perc1=namta(size(SST_V,1),size(SST_V,1))/sum(diag(namta));%%计算方差贡献率
figure;
plot(PC1);
title(['(a) EOF1=' num2str(perc1*100) '%']);
% d=diag(namta);%取出特征值矩阵列向量(提取出每一主成分的贡献率)
% namta_des=sort(d,'descend'); %将特征值矩阵列向量按照贡献率的大小descend降序排列
% v=fliplr(SST_V);       %将特征向量L按照特征值大小从上向下排列
% SST_V1=v(:,size(v,1));
% SST_Z=SST_V'*SST; %时间函数

%--------------EOF1海表温度重构---------------%
XP1=vec1*PC1;
XEOF=zeros(size(SST,1)*size(SST,2),size(SST,3));
[x,y]=find(isnan(X));%找出数据中的NAN值
for k=1:length(x)
XEOF(x(k),y(k))=nan;
end
reshape(XP1,size(XP1,1)*size(XP1,2),1);
[x1,y1]=find(~isnan(X));
for i=1:length(x1)
    XEOF(x1(i),y1(i))=XP1(i);
end
Xeof1=reshape(XEOF,size(SST,1),size(SST,2),size(SST,3));

figure
m_proj('miller','long',[115,135],'lat',[20,35]);
m_pcolor(lon,lat,mean(Xeof1,3));
m_grid('tickdir','out');
m_gshhs_l('patch',[0.8 0.8 0.8],'Edgecolor','none');
colorbar;
caxis([-0.05,0.02]);
colormap(jet);
title('2001年~2016年平均海表温度EOF1图');


%--------------EOF2---------------%
vec2=SST_V(:,size(SST_V,1)-1);
EOF2=vec2;%最大特征值对应特征向量即为第一EOF模态(空间函数)
EOF2=EOF2*sqrt(namta(size(SST_V,1),size(SST_V,1)));
PC2=vec2'*X3;%时间函数
PC2=PC2/sqrt(namta(size(SST_V,1),size(SST_V,1)));
perc2=namta(size(SST_V,1)-1,size(SST_V,1)-1)/sum(diag(namta));%计算方差贡献率
figure;
plot(PC2);
title(['(b) EOF2=' num2str(perc2*100) '%']);

%--------------EOF2海表温度重构---------------%
XP2=vec2*PC2;
XEOF=zeros(size(SST,1)*size(SST,2),size(SST,3));
[x,y]=find(isnan(X));
for k=1:length(x)
XEOF(x(k),y(k))=nan;
end
reshape(XP2,size(XP2,1)*size(XP2,2),1);
[x1,y1]=find(~isnan(X));
for i=1:length(x1)
    XEOF(x1(i),y1(i))=XP2(i);
end
Xeof2=reshape(XEOF,size(SST,1),size(SST,2),size(SST,3));

figure
m_proj('miller','long',[115,135],'lat',[20,35]);
m_pcolor(lon,lat,mean(Xeof2,3));
m_grid('tickdir','out');
m_gshhs_l('patch',[0.8 0.8 0.8],'Edgecolor','none');
colorbar
caxis([-0.05,0.02]);
colormap(jet);
title('2001年~2016年平均海表温度EOF2图');

  1. 结果如下:
    (1)第一模态和第二模态方差贡献率图像如下:
    用EOF分解16年东海月平均海表面温度_第1张图片
    用EOF分解16年东海月平均海表面温度_第2张图片
    (2)2001年至2016年月平均海表温度原始图像及其EOF1、EOF2图像如下:
    用EOF分解16年东海月平均海表面温度_第3张图片
    用EOF分解16年东海月平均海表面温度_第4张图片
    感谢写作业过程中帮助过我的同学们,老感谢了,真的!
    没有你们,我的作业就凉凉了,我真菜。Over~

你可能感兴趣的:(作业,Matlab作业)