气象数据基本处理

%1、数据预处理:

date_used=datevec(datenum(1979,1,1):1:datenum(2020,12,31));%构建时间向量,datevec把日期号datenum转化成向量形式

%date_used有六列,分别是年月日时分秒

sst_full=NaN(180,91,size(date_used,1));%预设空矩阵,三维:经纬度*时间

%批量读取mat文件:

for i=1979:2020;

index_here=ismember(date_used(:,1),i);%ismember判断数组元素是否为集数组成员,找date_used里第一列中i所在的位置index_here

load(['sst' num2str(i)]);%num2str将数字转化为字符数组

sst_full(:,:,index_here)=sst;

end

 

%2、时间格点,时间精度转换:把日精度的数据转化为月、年数据,也就是逐月平均sst_month和逐年平均sst_year

date_used=datevec(datenum(1979,1,1):1:datenum(2020,12,31));%构建时间向量,datevec把日期号datenum转化成向量形式

%unique数组中的唯一值

date_m=unique(date_used(:,1:2),'rows');%对1、2列沿行(rows)使用unique,提取出来年、月

date_y=unique(date_used(:,1),'rows');%对1列沿行使用unique,提取出来年

 

load('sst_full');

%先构建空数组用于之后储存月、年均值(每月、每年各自的均值,不是把所有月、年平均起来的一个二维数组)

sst_month=NaN(size(sst_full, 1), size(sst_full,2), size (date_m, 1)); 

sst_year=NaN(size(sst_full,1),size(sst_full,2),size(date_y,1));

 

for i=1: size(date_m, 1);

index_here=ismember(date_used(:,1:2), date_m(i,:), 'rows');%找到每个月份在date_used中的位置

sst_month (:,:,i)=nanmean(sst_full(:, :,index_here), 3) ;%将对应数据沿着第三维平均

end

for i=1:size(date_y, 1);

index_here=ismember(date_used(:, 1), date_y(i, :), 'rows');%找到每个年份在date_used中的位置

sst_year(:,:,i)=nanmean(sst_ful1(:,:,index_here),3);%将对应数据沿着第三维平均

end

 

%3、空间格点处理

%改图的中心位置:把中心是大西洋的改到太平洋,即西经180W-0-东经180E改为0-东经-180-西经-0,即-180~180改为0~360

 

lon (lon<0)=360+(lon (lon<0));

[lon_re,i]=sort (lon) ;%sort把lon从小到大排序。lon_re是重新排序后的经度,i是重排序后各数据的位置

%海温场的经度也重新排

sst_re=sst_full(i,:,:);

sst_re_m=sst_month(i,:, :);

sst_re_y=sst_year(i,:, :);

 

 

%4、基础的统计学参数:平均数Mean、中位数Median、标准差STD,5%、50%、95%的分位数Quantile

% only for sst_re here:

sst_mean=nanmean(sst_re ,3);%nan移除缺失值,3是指沿着时间维度计算

sst_med=nanmedian(sst_re,3);

sst_std=nanstd(sst_re,0,3);

sst_5q=quantile(sst_re,0.05,3);

sst_95q=quantile(sst_re,0.95,3);

sst_50q=quantile(sst_re,0.5,3);

%计算结果可以画成六张图,每个结果都是二维图

figure('pos', [10 10 1500 650], 'color', 'k');

t=tiledlayout (2,3, 'TileSpacing','Compact', 'Padding', 'Compact');%2行3列的拼图

date_name={'sst_mean','sst_med','sst_std','sst_5q','sst_50q','sst_95q'};%cell数据储存六个变量名

title_name={'a)mean','b)median','c)std','d)5%','e)50%','f) 95%'};%cell数据储存六个标题

 

for i=1:6

nexttile;

m_proj('miller', 'lon', [0 360], 'lat', [-90 90]);

if i~=3;

m_contourf(lon_re, lat,(eval(data_name{i}))', linspace(-2,30,200), 'linestyle', 'none');

% m_contourf绘制色块图,eval把字符串data_name{i}转化成程序语言

else %对第三张图特殊处理,std数据大小跟别的图不一样,用的色块范围不一样

m_contourf(lon_re, lat, (eval(data_name{i}))', linspace (0, 12,200), 'linestyle', 'none');

end

m_coast('patch', [0.7 0.7 0.7], 'linewidth',2); 

m_grid('fontsiz', 12, 'linestyle','none' ,'color','w');

colormap (m_colmap('jet')) ;

s=colorbar ('color', 'w');

title(s, '^{o}C', 'color','w');

if i~=3

caxis([0 32]);

else %第三张图

caxis ([0 8]);

end

ttl = title(title_name{i});

ttl.Units = 'Normalize';

ttl.Position (1) = 0;

tt1.HorizontalAlignment = 'left';

ttl.Color= 'w'

end

 

%5、季节性,here通过计算对应月份的全时间月平均来看季节性

load ('sst_re');

date_used=datevec(datenum (1979, 1, 1) :1 : datenum (2020, 12, 31)) ;

sst_season=NaN(size(sst_re,1), size(sst_re,2), 12);%应该得到每个月一张图,每个月一个二维矩阵

for i=1:12;

sst_season (:,:,i)=nanmean(sst_re(:,:, date_used(:,2)==i) ,3) ;%对sst_re月份为i的部分沿着时间平均

%date_used(:,2)==i应该是返回一组数,这组数字是所有i月份在date_used中的位置,也就是date_used第二列为i的位置

end

%12张图画一起

figure('pos', [10 10 1500 1200], 'color', 'k');

t=tiledlayout (3,4, 'TileSpacing','Compact', 'Padding', 'Compact');

title_full={'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'}; 

for i=1:12

ax=nexttile;

m_proj('miller', 'lon', [0 360], 'lat', [-90 90]);

m_contourf(lon_re, lat, (sst_season(:,:,i)-sst_mean)',linspace(-12, 12,300), 'linestyle', 'none');

%这里画的是各个月的平均与全平均的差值

m_coast('patch',[0.7 0.7 0.7], 'linewidth' ,2);

m_grid('fontsiz',12, 'linestyle','none', 'color', 'w');

colormap (m_colmap ('diverging'));

caxis ([-4 4]);

ttl = title(title_full{i});

ttl.Units = 'Normalize';

tt1. Position (1) = 0;

tt1.HorizontalAlignment = 'left';

ttl.Color= 'w';

if ismember(i, [12 4 8]);

s=colorbar (ax, 'color', 'w');

end

end

 

 

%6、差异值anomaly

%以年为周期的多样性叫做气候态或者季节性气候态~计算方法很多

%here气候态:按照最小时间单位求取年内每个时间点的平均值。日精度数据,也就是365天中的每一天都求多年这一天的平均值。月精度数据,1月的气候态就是所有年份1月的平均值。年数据没有气候态可算

%移除了季节性气候态之后的是anomaly

date_daily=datevec(datenum(1979,1,1):datenum(2020,12,31));

date_month=unique(date_daily(:,1:2),'rows'); %用unique找出年和月

unique_d=unique(date_daily(:,2:3),'rows');%用unique找出月和日 得到366*2

unique_m=(1:12)';

sst_anom_d=NaN(size(sst_re));%size(sst_re)是三维海温场,日数据

sst_anom_m=NaN(size(sst_re_m));%

 

for i=1: size(unique_d, 1); %size(unique_d, 1)=366

index_here=ismember(date_daily(:,2:3),unique_d(i,:),'rows');%找到对应位置,同一个日期

sst_anom_d(:,:,index_here)=sst_re(:,:,index_here)-nanmean(sst_re(:,:,index_here),3);

end

for i=1: size(unique_m, 1) ;

index_here=ismember(date_month(:, 2) , unique_m(i, :), 'rows');%找到对应位置,同一个月份

sst_anom_m(:,:,index_here)=sst_re_m(:,:,index_here)-nanmean(sst_re_m(:,:,index_here),3);

end

 

%7、空间平均

%权重参数cos纬度

[lat,lon]=meshgrid(lat,lon_re);

data_name={'sst_anom_d','sst_anom_m','sst_re_y'};

output_name={'local_d','local_m','local_y'};

for i=1:length(data_name);

eval([data_name{i} '=' data_name{i} '.*repmat(cosd(lat),1,1,size(' data_name{i} ',3));']) ; %先将输入的数据乘上cos纬度来权重

eval([output_name{i} '=NaN(size(' data_name{i} ',3),6);'])

eval(['d3=' data_name{i} ';']);

%permute函数改变数据维度位置,指定的顺序重新排列数组的维度

d2=permute(d3,[3 1 2]);

d2=reshape(d2,size(d2,1),size(d2,2)*size(d2,3));

%permute和reshape将本来维度为经度、纬度、时间的三维数据转换化成时间*空间的二维数据

 

%然后根据区域范围

%1 Indian Ocean

ts_here=nanmean(d2(:,lon(:)>=20 & lon(:)<=110 & lat(:)>=-20 & lat(:)<=30), 2);

eval([output_name{i} '(:,1)=ts_here;'])

%2 North Pacific

ts_here=nanmean(d2(:,lon(:)>=120 & lon(:)<=240 & lat(:)>=0 & lat(:)<=66.5), 2); 

eval([output_name{i} '(:,2)=ts_here;'])

%3 South Pacific

ts_here=nanmean(d2(:,lon(:)>=140 & lon(:)<=300 & lat(:)>=-66.5 & lat(:)<=0), 2);

eval([output_name{i} '(:,3)=ts_here;'])

%4 North Atlantic

ts_here=nanmean(d2(:,lon(:)<=5 & lon(:)>=110 & lat(:)>=0 & lat(:)<=66.5), 2);

eval([output_name{i} '(:,4)=ts_here;'])

%5 Eq Pacific

ts_here=nanmean(d2(:,lon(:)>=120 & lon(:)<=280 & lat(:)>=-20 & lat(:)<=20), 2);

eval([output_name{i} '(:,5)=ts_here;'])

%6 global

ts_there=nanmean(d2(:,abs(lat(:))<66.5),2);

eval([output_name{i} '(:,6)=ts_there;'])

%把结果分别存到了'local_d','local_m','local_r'

%每个数据都是一个行数对应时间点数,列数为6分别对应六个空间

end

 

%8、线性趋势 常用函数:polyfit不全, regress, fitlm太全计算量大

% b = regress(y,X) 或者 [b, bint] = regress(y,X) 

%y是响应变量。 X是解释变量,不是向量,至少两列,第一列必须全部为1。 

%得到的b是系数们,第一个是常数项,第二个是一次项系数

%bint是对应参数95%的置信区间上下限,如果区间范围不包含0就说明参数在95%置信区间内统计学显著

 

%以下用月SST来做个线性趋势分析。遍历空间点,对每个位置都做了时间序列的线性回归

sst_anom_d=sst_anom_m;

coef_sst=NaN(size(sst_anom_d, 1),size(sst_anom_d,2));

cint_sst=NaN(size(sst_anom_d, 1), size(sst_anom_d,2),2) ; 

time_full=(1:size(sst_anom_d,3))';

 

for i=1:size(sst_anom_d, 1);

tic

for j=1: size (sst_anom_d, 2);

ts_here=squeeze(sst_anom_d(i,j,:));

if nansum(isnan(ts_here))~=length(ts_here);

[b,bint]=regress(ts_here, [ones(length(ts_here), 1) time_full]);

coef_sst(1,j)=b(2); %得到的参数都储存在这

cint_sst(i,j,:)=bint(2,:); %得到的置信区间上下限

end

end

toc

end

%结果用点图表示,scatter

 

%9、滑动线性趋势,相当于计算变化的瞬时速度,在较短的一定时间区域内计算其趋势。类似于滑动平均,把要平均的步骤换成求趋势

%形成的结果可以是一张折线图,每点的趋势还可以带上个置信区间

%画图:循环6次把6条线画到同一张图

figure('pos', [10 10 1200 800]);

load('sst_moving_trend.mat');

legend_used={'Indian Ocean', 'North Pacific', 'South Pacific', 'North Atlantic','Equatorial Pacific', 'Global'};

color= [0 0.4470 0.7410;...

[0.8500 0.3250 0.0980];

[0.9290 0.6940 0.1250];

[0.4940 0.1840 0.5560];

[0.4660 0.6740 0.1880];

[0 0 0]];

for i=1:6;

h=errorbar((1979:2020)',mtrend(:,i)*120, (mint(:,i,2)-mint(:,i,1))*120./2, '-s', 'Markersize', 10, 'linewidth' ,2, 'markeredgecolor', color (i,:), 'markerfacecolor' ,color(i,:),'color' ,color(i,:));

%errorbar,绘制每条线及其点上的置信区间。根据输入的前两个变量产生线图。第三个变量指定置信区间宽度,就是/2的那块。

hold on

eval(['h' num2str(i) '=h'])

end

yline(0, '--');

legend([h1 h2 h3 h4 h5 h6], legend_used, 'location', 'best', 'fontsize', 12);

set (gca, 'fontsize', 16) ; 

ylabel('^{o}C/decade');

 

 

你可能感兴趣的:(matlab)