MATLAB将单元格数组保存到NetCDF文件中

时间:2014-01-10 20:02:01

标签: matlab netcdf

我有一个.csv文件,我使用导入数据函数作为列向量导入到MATLAB中。 .csv文件中的每一列现在都是一个大小为7286x1的单元格数组。如何将每个列向量作为变量保存到netcdf文件中?

ncid = netcdf.create('WI_O3.nc', 'NOCLOBBER');
dimid = netcdf.defDim(ncid, 'my_dim', 7286);
SiteID = netcdf.defVar(ncid, 'AQS_SITE_ID', 'double', dimid);
netcdf.endDef(ncid);
netcdf.putVar(ncid, SiteID, AQS_SITE_ID);
    % Error using netcdf.putVar (line 56)
    % Expected DATA to be one of these types:
    % 
    % double, single, uint8, uint16, uint32,
    % uint64, int8, int16, int32, int64, char
    % 
    % Instead its type was cell.

如何将我的所有单元格转换为字符串或双精度或任何可以使其工作的单元格?我的一些单元格由单词(字符串)组成,而其他单元格则是数字(双精度)

是否有更快的方法将工作空间中的所有变量保存到一个.nc文件中(保持所有变量名称相同)?

3 个答案:

答案 0 :(得分:4)

这不完全是你提出的问题,但这是一个脚本,它将结构中的所有{double,single,char}变量写入netcdf文件。它不是最通用的代码,因为我只处理3D变量(尽管这很容易扩展)。我在这里发布它是因为我认为它可能具有普遍的用途和兴趣,也许有人甚至会发布更好的版本。

我还压缩所有非标量或char的变量。

function struct2nc(x,ncfile,ncfiletype,deflate_lev)
% STRUCT2NC writes all float,double and character vars to netcdf
% Usage: struct2nc(x,ncfile,[ncfiletype],[deflate_lev])
% x = structure
% ncfile = name of netcdf output file (e.g. 'test.nc')
% ncfiletype = netcdf file type (e.g. 'classic','netcdf4_classic')
% deflate_lev = deflate level (0-9, 0 is none)
%
% This function writes all 'double','single' and 'char' variables
% to NetCDF using the native Matlab NetCDF interface.  It skips all
% other classes in the struct (e.g. structs, cell arrays, etc).  It
% also only handles scalar, 1D, 2D, and 3D arrays currently, although
% this could easily be extended.

if nargin==2,
    ncfiletype='classic';
    deflate_lev=0;
elseif nargin==3;
    switch ncfiletype
        case {'netcdf4','netcdf4_classic'}
            deflate_lev=6;
        otherwise
            deflate_lev=0;
    end
end
s = fieldnames(x);
k=0;
% create variables first, but don't write data
for i=1:length(s)
    vname=char(s(i));
    var=x.(vname);
    vtype = class(var);
    vshape = size(var);
    ndims = length(vshape);
    vlen = length(var(:));
    switch vtype;
        case {'double','single'},
            if vlen==1,
                nccreate(ncfile,vname,...
                    'Datatype',vtype,'format',ncfiletype);
                k=k+1;
                vnames{k}=vname;
            else
                if min(vshape)==1,
                    nccreate(ncfile,vname,...
                        'Datatype',vtype,...
                        'DeflateLevel',deflate_lev,...
                        'Dimensions',{[vname '1'] vlen},...
                        'format',ncfiletype);
                    k=k+1;
                    vnames{k}=vname;
                elseif ndims==2,
                    nccreate(ncfile,vname,...
                        'Datatype',vtype,...
                        'DeflateLevel',deflate_lev,...
                        'Dimensions',{[vname '1'] vshape(1) [vname '2'] vshape(2)},...
                        'format',ncfiletype);
                    k=k+1;
                    vnames{k}=vname;
                elseif ndims==3,
                    nccreate(ncfile,vname,...
                        'Datatype',vtype,...
                        'DeflateLevel',deflate_lev,...
                        'Dimensions',...
                        {[vname '1'] vshape(1) [vname '2'] vshape(2) [vname '3'] vshape(3)},...
                        'format',ncfiletype);
                    k=k+1;
                    vnames{k}=vname;
                else,
                    disp('Skipping variable with more than 3 dimensions');
                end
            end
        case {'char'},
            nccreate(ncfile,vname,...
                'Datatype',vtype,...
                'Dimensions',{[vname '1'] vlen},.....
                'format',ncfiletype);
            k=k+1;
            vnames{k}=vname;
        otherwise,
            disp(['skipping ' vname])
    end
end
%write all the data at the end
for i=1:length(vnames)
    ncwrite(ncfile,vnames{i},x.(vnames{i}));
end

答案 1 :(得分:0)

netcdf。*函数是用于直接访问NetCDF库的低级函数。 使用ncwrite和nccreate。

查看NCCREATE的example和NCWRITE的example,其中显示了如何创建变量以及所需的尺寸然后写入。 (NCWRITE文档页面中的第二个示例应该是一个很好的起点)。

NetCDF格式不支持“细胞”。在MATLAB中创建一个ND变量作为普通数字数组,然后将其写入NetCDF文件。

答案 2 :(得分:0)

有趣的问题。 AFAIK,NetCDF3和NetCDF4格式没有任何类似于Matlab的单元阵列,它可以在每个单元中保存不同类型的数据。不幸的是,Matlab目前(1/18)都不支持读取和写入NetCDF4的可变长度字符串(即使它最近添加了一个字符串数据类型)。

所以,有两种可能的解决方案。

  1. 使用sprintf(...)将所有数字数据转换为字符串。不幸的是,这些必须是固定长度的字符串,这需要足够长以保持必要的精度。然后将数据存储为固定长度的2-D char数组。

  2. 使用数值对字符串数据进行编码。例如,如果你有" Ozone"," CO2","甲烷"的字符串,用例如-999,-998和-997替换它们分别。 (显然,选择实际数据中不会出现的数值。)这类似于您需要编码由_FillValue属性标记的nan的方式。您还应该将标志和相应的原始字符串存储为属性或单独的字符数组和关联的标志值。