登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
nc数据全解读-2 matlab读取方法ncread、netcdf
参考了一个网上大神的视频。。。只剩下载的视频,找不到出处了,那也得云感谢一下 可以直接看附件,一个文档,先看ncstudy2.m,再看gaoweiduHGT.m
1高级函数读取法ncread
我们在1中用air=ncread('air.mon.mean.nc','air');直接读取air,数据是144*73*865,可以叫格点法高级函数读取(因为简单所以高级。。。。)。通过观察经纬度排列,知道对应经纬度的格点,直接实现了具体时段、具体区域的数据读取。
但有些时候会导致数据过大,占内存严重,可以用domain直接限定ncread读取的经纬度范围,从而缩小数据量,不直接读air了!!!
1.1读取方法同上篇
1.2 domain限定经纬度范围的数据读取,直接读取用的数据。
domain=[115117.5 37.5 40];%限定北京范围东经115-117.5,北纬37.5-40
ncdisp('air.mon.mean.nc');%hgt.mon.mean.nc是1948年1月-2020年1月
lat=ncread('air.mon.mean.nc','lat');
lon=ncread('air.mon.mean.nc','lon');
!!!本质上还是格点法,因为domain度数之后返回的lonk,latk都是点数。。。。
lonk1=find(lon==domain(1));%选定lon的起始点东经115度对应第47个经度(间隔2.5),
lonk2=find(lon==domain(2));%选定lon的结束点东经117.5度对应第48个,
latk1=find(lat==domain(4));%选定lat的起始点北纬40对应第21个纬度(间隔2.5),
latk2=find(lat==domain(3));%选定lat的结束点北纬37.5度对应第22个纬度,
%time1=find(lat==domain(5));%选定lat的起始点北纬52.5对应第16个纬度(间隔2.5),
%time2=find(lat==domain(6));%选定lat的结束点北纬5度对应第61个纬度,
%开始选取区域
airbj=ncread('air.mon.mean.nc','air',...
[lonk1 latk1 1],[lonk2-lonk1+1 latk2-latk1+1 12]);%airbj与bjair48完全一致
%air是三维数据,第一维经度,第二维纬度,第三维是时间。1,12是选取的时间,1是开始,第12结束,若12换成inf,则全读865个月,也可以任意选定时间段。
fori=1:1:12;
airbj2=squeeze(airbj(:,:,i));%airbj2是第12个月的北京区域数值,前面11个数值被覆盖了
airbj1948(i,:)=reshape(airbj2,1,4);%将三维变量变为二维,airbj1948和上一篇中beijing1948完全一致。
end
%最后检测missing_value,以防万一
missing_records=ncreadatt('air.mon.mean.nc','air','missing_value');%检测missing_value,以防万一
airbj1948(airbj1948==missing_records)=NaN;%将缺省值补上
size(airbj1948)
2读取的低级函数netcdf
2.1低级函数变量法读取
由nc数据全解读-1数据下载,nc简单matlab读取、数据内部结构介绍中3.1可知,air数据是三个维度,四个变量,重点是低级函数中变量是从0开始,也就是四个变量lat、lon、time、air的排序是0、1、2、3。内部数据也是从0开始,865个月是0-864
程序如下:
clearall
fid=netcdf.open('air.mon.mean.nc','NC_NOWRITE');%读取nc格式数据,'NC_NOWRITE'写保护,不能更改数据。
ncdisp('air.mon.mean.nc');%air.mon.mean.nc是1948年1月-2020年1月
latd=netcdf.getVar(fid,0,'double');
lond=netcdf.getVar(fid,1,'double');
timed=netcdf.getVar(fid,2,'double');
aird=netcdf.getVar(fid,3,'double');%得出温度(共144*73*865个数据)
得到的数据完全同以前的一样,也可以接着用domain限定区域,用法同上,但是值得注意!!!!摘自别处------低级函数使用domain时千万注意。数据是从0开始排序的,865个月是0-864,73个纬度是0-72,我的matlab不存在这个问题,也不大懂这一块,还是用ncread好一点。。。。推测可能跟matlab版本有关,旧的存在,新的不存在这个问题。欢迎指正。
低版本matlab低级函数netcdf使用domain程序如下:
domain=[115117.5 37.5 40];%限定北京地区范围E115-117.5, N37.5-40
lonk3=find(lon==domain(1));%选定lon的起始点东经115度对应第47个经度(间隔2.5),
lonk4=find(lon==domain(2));%选定lon的结束点东经117.5度对应第48个,
latk3=find(lat==domain(4));%选定lat的起始点北纬40对应第21个纬度(间隔2.5),
latk4=find(lat==domain(3));%选定lat的结束点北纬37.5度对应第22个纬度,
airdbj=netcdf.getVar(fid,3,[lonk3-1 latk3-1 0],...
[lonk4-lonk3+1 latk4-latk3+1 12],'double');%
得到的airdbj 与以前的bjair48一致。
file:///C:/Users/Administrator/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
通过下面命令,可能看到最小值最大值不符合常理
size(airdbj)
maxairdbj=max(airdbj(:));
minairdbj=min(airdbj(:));
这是因为scale_factor和add_offset的原因
因为我的scale_factor(系数)是1,所以是正常的
file:///C:/Users/Administrator/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
如果不是1,则
sf=netcdf.getAtt(fid,3,'scale_factor','double');%得到air的系数
addoff=netcdf.getAtt(fid,3,'add_offset','double');%得到air的余数
airdbjzuizhong=airdbj.*sf+addoff;
可以得出最终正确数据
2.2,低级函数不详细区分第几变量,简单粗暴法
ncid=netcdf.open('air.mon.mean.nc','NC_NOWRITE');%读取nc格式数据
lonid =netcdf.inqVarID(ncid,'lon');%返回经度信息,0-180是东经,180-360对应着西经的180-0
lon22=netcdf.getVar(ncid,lonid); %得出全球经度范围在2.5的精度下(0:2.5:357.5),既全球360度划分为144个区域,1-73既东半球(东经0-180度);73-144既西半球(西经180-0度)
latid =netcdf.inqVarID(ncid,'lat');
lat22=netcdf.getVar(ncid,latid);%得出全球纬度范围在2.5的精度下,既全球180度划分为73个区域,1-37既北半球(北纬90-0);37-73既南半球(南纬0-90);
%全球纬度的格式是90:-2.5:-90,共有73个数据,赤道正好是0;是第37个数据
timeid =netcdf.inqVarID(ncid,'time');%返回时间信息
time22=netcdf.getVar(ncid,timeid); %得出时间范围:1948年1月-2015年3月份 (共807个月);50年1月是第25个数据
airid =netcdf.inqVarID(ncid,'air');%返回变量850hpa高度的值
air22=netcdf.getVar(ncid,airid);%得出高度(共144*73*807个数据)
3更高维度,四维数据五维变量的读取
上面都是三维数据lon、lat、time,加一个要素air的读取,有时还会有高度层选取,比如hgt.mon.mean.nc数据有17层,也就是四维数据五维变量
从下面网址选hgt数据
https://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanalysis.derived.pressure.html file:///C:/Users/Administrator/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
ncdisp('hgt.mon.mean.nc');
之后发现4维、5变量
Dimensions:
level = 17
lat = 73
lon = 144
time = 865 (UNLIMITED)
Variables:
level
Size: 17x1
Dimensions:level
Datatype: single
Attributes:
units = 'millibar'
long_name = 'Level'
positive = 'down'
GRIB_id = 100
GRIB_name = 'hPa'
actual_range = [1000 10]
axis = 'Z'
lat
Size: 73x1
Dimensions:lat
Datatype: single
Attributes:
units = 'degrees_north'
actual_range = [90 -90]
long_name = 'Latitude'
standard_name = 'latitude'
axis = 'Y'
lon
Size: 144x1
Dimensions:lon
Datatype: single
Attributes:
units = 'degrees_east'
long_name = 'Longitude'
actual_range = [0 357.5]
standard_name = 'longitude'
axis = 'X'
time
Size: 865x1
Dimensions:time
Datatype: double
Attributes:
long_name = 'Time'
delta_t = '0000-01-0000:00:00'
avg_period = '0000-01-0000:00:00'
prev_avg_period = '0000-00-01 00:00:00'
standard_name = 'time'
axis = 'T'
units = 'hours since1800-01-01 00:00:0.0'
actual_range = [1297320 1928472]
hgt
Size: 144x73x17x865
Dimensions:lon,lat,level,time
Datatype: single
Attributes:
long_name = 'Monthlymean geopotential height'
valid_range =[-700 35000]
units = 'm'
add_offset = 0
scale_factor = 1
missing_value =-9.969209968386869e+36
precision = 0
least_significant_digit = 0
GRIB_id = 7
GRIB_name = 'HGT'
var_desc ='Geopotential height'
level_desc ='Multiple levels'
statistic = 'Mean'
parent_stat = 'Other'
dataset = 'NCEPReanalysis Derived Products'
actual_range =[-354.458344 32321.0977]
%hgt=ncread('hgt.mon.mean.nc','hgt');直接读取数据量太大144*73*17*865(还得再*8浮点才是数据量),处理较慢
直接domain
lat=ncread('hgt.mon.mean.nc','lat');
lon=ncread('hgt.mon.mean.nc','lon');
lvl=ncread('hgt.mon.mean.nc','level')
time=ncread('hgt.mon.mean.nc','time');
%hgt=ncread('hgt.mon.mean.nc','hgt');
domain=[115 117.5 37.5 40]
lonk1=find(lon==domain(1));%选定lon的起始点东经115度对应第47个经度(间隔2.5),
lonk2=find(lon==domain(2));%选定lon的结束点东经117.5度对应第48个,
latk1=find(lat==domain(4));%选定lat的起始点北纬40对应第21个纬度(间隔2.5),
latk2=find(lat==domain(3));%选定lat的结束点北纬37.5度对应第22个纬度,
%开始选取区域
hgtbj=ncread('hgt.mon.mean.nc','hgt',...
[lonk1 latk1 3 1],[lonk2-lonk1+1 latk2-latk1+1 1 12]);%第一个中括号应该是开始的经度、纬度、层次、时间,第2个中括号总共要读的经度数、纬度数、总的层次数量、时间数
%[lonk1 latk1 3 1]3代表第三层850hpa,1代表从第一个月开始
%[lonk2-lonk1+1 latk2-latk1+1 1 12],1代表只有850一层,12表示到第12个月结束,也可以换成inf,代表到2020年1月
hgtbj2=squeeze(hgtbj)%4维变3维
若继续变2维,跟以前多次处理一致,看下面
for i=1:1:12;
hgtbj3=squeeze(hgtbj(:,:,i));%hgtbj3是第12个月的北京区域850hap数值,前面11个数值被覆盖了
hgtbj48(i,:)=reshape(hgtbj3,1,4);%将三维变量变为二维,
end
|