【问题标题】:MATLAB Save Cell Arrays to NetCDF FileMATLAB 将元胞数组保存到 NetCDF 文件
【发布时间】:2014-01-29 23:06:18
【问题描述】:

我有一个 .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 文件中(保持所有变量名称相同就可以)?

【问题讨论】:

    标签: matlab netcdf


    【解决方案1】:

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

    我还压缩了所有非标量或字符的变量。

    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
    

    【讨论】:

    【解决方案2】:

    netcdf.* 函数是用于直接访问 NetCDF 库的低级函数。 将 ncwrite 与 nccreate 一起使用。

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

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

    【讨论】:

    • 当单元格为“臭氧”之类的内容时,我无法将其转换为字符串。帮助?我试过cellstr 但这确实有效
    • 另外,我必须单独添加每个变量?
    【解决方案3】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2014-06-03
      • 2013-10-03
      • 2013-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多