哈喽!大家好,这里是小Yang!
上一章向大家分享了如何从官网获取Argo数据,以及它所被记录的文件格式—dat文件,那么这部分小Yang将向大家继续分享一下如何读取dat文件的内容吧!
- dat文件数据内容的分析
- dat文件数据的提取
- dat文件提取Argo的编号、数据提取时间和Argo的位置信息
dat文件数据内容的分析
我们在MATLAB打开任意一个dat文件的时候,可以发现它包含了这些信息:
其中,我们比较感兴趣的信息一般有Argo的编号(PLATFORM NUMBER)、它获得该数据的具体时间(JULIAN DAY)、它所在的位置–经纬度(LOCATION)、以及它所测得的数据(FILE)。在MATLAB,我们可以用importdata
来读取dat文件,先在命令行窗口测试一下:
接着会得到一个结构体数组,可以继续输入ans.data
和ans.textdata
来分别进一步查看里面的内容。
对于ans.data
部分,小Yang这里就不多展示啦,从‘double’可见,里面其实就是该Argo测得的一些海洋物理参数,比如垂向温度分布、盐度分布等。如果想要提取到文件与Argo有关的基本信息,我们更多是要对ans.textdata
部分进行处理,这一部分的内容是元胞形式的:
以上就是dat文件的基本内容,下面一起来看看怎么提取dat文件的基本信息吧!
dat文件数据的提取
dat文件提取Argo的编号、数据提取时间和Argo的位置信息
参考杭州Argo官网提供的解析dat文件的源程序"read_data_from_single_file”(在进入ftp链接后的“matlab”文件夹中可以找到,但是该程序只能读一些Argo基本参数,无法读取我们想要的参数),可以利用识别每个cell中包含的字符来判断该cell是否为我们所需要。
话不多说,先上代码!
看不懂没关系!小Yang后面会一步步解释
function [SID,date,lon,lat] = read_time_coord_from_dat(filename)
% READ_TIME_COORD_FROM_DAT 输出argo的编号、时间和坐标
argodata=importdata(filename);
l=length(argodata.textdata);
n=0;
for i=1:l
if strncmp(argodata.textdata(i),' PLATFORM NUMBER',20)
SID=split(argodata.textdata(i),':');
SID=SID(2);
n=n+1;
elseif strncmp(argodata.textdata(i),' JULIAN DAY',15)
date=split(argodata.textdata(i),'(');
date=split(date(1),':');
date=str2double(cell2mat(date(2)))+712224;
date={datetime(date,'ConvertFrom','datenum')};
n=n+1;
elseif strncmp(argodata.textdata(i),' LATITUDE',13)
lat=split(argodata.textdata(i),':');
lat=lat(2);
n=n+1;
elseif strncmp(argodata.textdata(i),' LONGITUDE',14)
lon=split(argodata.textdata(i),':');
lon=lon(2);
n=n+1;
elseif n >= 4
break
end
end
if n<4
SID=[];
date=[];
lon=[];
lat=[];
end
end
为了在后面实现对多个dat文件同时处理,小Yang也使用了函数的形式来编译。
首先是函数句柄的形式,比较基础的啦,小Yang就不深入解释,总之该函数希望达到的目的就是:输入文件名,能够返回一个数组,数组包含Argo的SID、记录数据的时间、经度、纬度这四个参数。
function [SID,date,lon,lat] = read_time_coord_from_dat(filename)
第二步:就是刚刚说的用importdata
来读取dat文件,并把读出来的两部分数据—data和textdata用argodata来保存。
argodata=importdata(filename);
第三步,也是最关键的部分:
l=length(argodata.textdata);
n=0;
for i=1:l
if strncmp(argodata.textdata(i),' PLATFORM NUMBER',20)
SID=split(argodata.textdata(i),':');
SID=SID(2);
n=n+1;
elseif strncmp(argodata.textdata(i),' JULIAN DAY',15)
date=split(argodata.textdata(i),'(');
date=split(date(1),':');
date=str2double(cell2mat(date(2)))+712224;
date={datetime(date,'ConvertFrom','datenum')};
n=n+1;
elseif strncmp(argodata.textdata(i),' LATITUDE',13)
lat=split(argodata.textdata(i),':');
lat=lat(2);
n=n+1;
elseif strncmp(argodata.textdata(i),' LONGITUDE',14)
lon=split(argodata.textdata(i),':');
lon=lon(2);
n=n+1;
elseif n >= 4
break
end
end
因为我们想要的数据在textdata中,因此只从该部分来提取。在讲解这部分内容之前,大家需要先知道strncmp
和split
的作用:
1.strncmp
:比较字符串的前 n 个字符(区分大小写)。小Yang直接摘一段官网的话吧:tf = strncmp(s1,s2,n) 比较 s1 和 s2 的前 n 个字符。如果二者相同,函数将返回 1 (true),否则返回 0 (false)。如果两个文本段的内容一直到结尾都相同或前 n 个字符相同(以先出现者为准),则将这两个文本段视为相同。返回结果 tf 的数据类型为 logical。
以代码为例,这段代码的意思就是:把argodata.textdata(i)
的前20个字符 (包括空格) 部分与' PLATFORM NUMBER'
这一段字符作比较,如果一模一样,那么判断为1,执行 if 中的语句,若不一样,那么就跳过。
if strncmp(argodata.textdata(i),' PLATFORM NUMBER',20)
可以回看一下在textdata中对应的部分:
所以当 i = 3 时,能通过识别,可以执行 if 语句中的部分。
2.split
:在分隔符处拆分字符串。 例如在代码中:
SID=split(argodata.textdata(i),':');
当 i = 3 时,执行 if 语句中的部分,此时argodata.textdata(i)
对应的就是上图的红色框部分,我们要提取出冒号后面的那一串数字,即Argo的编号,因此,用split
在冒号 ‘ :’处分割字符,原来的字符变成两部分,第一部分是冒号左边的' PLATFORM NUMBER '
,第二部分是冒号右边的数字'1900832'
。
再单独把第二部分提出来,用SID
来储存就好啦。这就是 if 语句中所包含的关键部分。
SID=SID(2);
后面的三个elseif
部分,原理是一模一样的,在此就不再赘述咯。
至于此处用到的n
,想法是每记录一个数据,n
就加1,当四个数据都记录完了,此时n=4
,可以直接跳出循环,而不需要把整个argodata.textdata
都遍历一次。
elseif n >= 4
break
end
第四步:若整个argodata.textdata
都遍历一次后,但 n
还是小于4,说明该dat文件存在数据缺失,因此跳过该dat文件的读取,并把可能读取到的部分信息(如SID)清空,说明这个dat文件无法正常读取。
if n<4
SID=[];
date=[];
lon=[];
lat=[];
end
那么,以上就是dat文件提取Argo的编号、数据提取时间和Argo的位置信息的内容,如果对你有帮助的话,可以收藏一下啦
下一部分, 小Yang将向大家分享一下如何一次性读取dat文件夹的所有dat文件!