如何使用Matlab将.mat转换为.nc?

zynd9foi  于 7个月前  发布在  Matlab
关注(0)|答案(1)|浏览(245)

我想把一个同事发给我的.mat数据转换成netcdf数据,以便在另一个项目中使用它们。我平时不会用matlab,所以对它没有很多经验。我下载Matlab来进行转换,并编写了一个脚本来打开.mat数据,从中提取数据(pldrelease_datexy),创建一个netcdf文件,定义尺寸,定义变量并将数据写入变量。
然而,我的脚本的最后一步不起作用,matlab错误指示:
使用matlab.internal.imagesci.netcdflib时出错
输入元素的数量与变量大小不匹配。
下面是我正在尝试转换的文件的链接:https://drive.google.com/file/d/1Rxz1kBg5eLbJuEfHpPYPDrjUjfoacAD1/view?usp=sharing
这个.mat数据是一个1x1结构,有4个字段:

  • pld 4492500x1双
  • release_date 4492500x1双
  • x 4492500x72双
  • y 4492500x72双

这是我现在使用的代码:

% Define the path to the folder containing .mat files
folder_path = 'D:/.../output_test';

% Get a list of .mat files in the folder
mat_files = dir(fullfile(folder_path, '*.mat'));

% Loop through each .mat file
for i = 1:numel(mat_files)
    mat_file = mat_files(i);
    mat_data = load(fullfile(folder_path, mat_file.name));
    
    % Extract data from the loaded struct
    pld = mat_data.pld;
    release_date = mat_data.release_date;
    x = mat_data.x;
    y = mat_data.y;
    
    % Create a NetCDF file
    nc_file = strrep(mat_file.name, '.mat', '.nc');
    ncid = netcdf.create(nc_file, 'NETCDF4');
    
    % Define dimensions
    dim_x = netcdf.defDim(ncid, 'x', size(x, 2));  
    dim_y = netcdf.defDim(ncid, 'y', size(x, 2));  
    
    % Define variables
    var_pld = netcdf.defVar(ncid, 'pld', 'double', [dim_x, dim_y]);
    var_release_date = netcdf.defVar(ncid, 'release_date', 'double', [dim_x, dim_y]);
    var_x = netcdf.defVar(ncid, 'x', 'double', [dim_x, dim_y]);
    var_y = netcdf.defVar(ncid, 'y', 'double', [dim_x, dim_y]);
    
    % Complete the definition of the NetCDF file
    netcdf.endDef(ncid);
    
    % Write data to variables
    netcdf.putVar(ncid, var_pld, pld);
    netcdf.putVar(ncid, var_release_date, release_date);
    netcdf.putVar(ncid, var_x, x);
    netcdf.putVar(ncid, var_y, y);
    
    % Close the NetCDF file
    netcdf.close(ncid);
end
hgc7kmma

hgc7kmma1#

首先,让我们在这里澄清MATLAB部分。关于这些矩阵的大小,您是正确的。MATLAB中的size函数为您提供指定的每个维度的大小。

  • size(x)等于向量[4492500, 72]
  • size(x, 1)等于4492500
  • size(x, 2)等于72
  • size(x, 72)等于1(因为这意味着这个2D矩阵在所有更高的维度上都是平坦的)。这没用

现在,如果我们想要的只是以标准格式存储这些数据,那么可以使用HDF5,甚至不关心每个数据集有多少维度(我只是根据示例文件中的值猜测正确的DataType)。

h5_file = strrep(mat_file.name, '.mat', '.h5');

h5create(h5_file, '/pld', size(mat_data.pld), DataType='uint8');
h5create(h5_file, '/release_date', size(mat_data.release_date), DataType='int8');
h5create(h5_file, '/x', size(mat_data.x), DataType='double');
h5create(h5_file, '/y', size(mat_data.y), DataType='double');

h5write(h5_file, '/pld', mat_data.pld);
h5write(h5_file, '/release_date', mat_data.release_date);
h5write(h5_file, '/x', mat_data.x);
h5write(h5_file, '/y', mat_data.y);
h5disp(h5_file); % just to inspect
HDF5 test.h5 
Group '/' 
    Dataset 'pld' 
        Size:  4492500x1
        MaxSize:  4492500x1
        Datatype:   H5T_STD_U8LE (uint8)
        ChunkSize:  []
        Filters:  none
        FillValue:  0
    Dataset 'release_date' 
        Size:  4492500x1
        MaxSize:  4492500x1
        Datatype:   H5T_STD_I8LE (int8)
        ChunkSize:  []
        Filters:  none
        FillValue:  0
    Dataset 'x' 
        Size:  4492500x72
        MaxSize:  4492500x72
        Datatype:   H5T_IEEE_F64LE (double)
        ChunkSize:  []
        Filters:  none
        FillValue:  0.000000
    Dataset 'y' 
        Size:  4492500x72
        MaxSize:  4492500x72
        Datatype:   H5T_IEEE_F64LE (double)
        ChunkSize:  []
        Filters:  none
        FillValue:  0.000000

当然你也可以选择在这里创建群组等等。
如果我们想使用NetCDF格式,我们需要了解它是如何设计的,以及维度的含义。
我不知道这个数据意味着什么,你必须定义具有4492500元素的维度意味着什么,以及具有72元素的维度意味着什么。这里不是x和y维度。这是一个问题,i和j索引将意味着x(i,j)。我假设这些都是连接考虑到重复发生的大小,但它在技术上将是无关的。
我猜这是许多随时间变化的样本,所以4492500是时间维度。然后72号就成了...位置维度?我真的不能从数据中判断出它可能是什么,因为它都是NaN值。

dim_time = netcdf.defDim(ncid, 'time', size(x, 1));  % 4.5 million long
dim_location = netcdf.defDim(ncid, 'location', size(x, 2));  % 72 long

现在我们准备定义变量

var_pld = netcdf.defVar(ncid, 'pld', 'ubyte', [dim_time]);
var_release_date = netcdf.defVar(ncid, 'release_date', 'byte', [dim_time]);
var_x = netcdf.defVar(ncid, 'x', 'double', [dim_time, dim_location]);
var_y = netcdf.defVar(ncid, 'y', 'double', [dim_time, dim_location]);

(rest代码应该按原样工作)

注意我只有一个文件,如果pldrelease_date可以取更大的值,那么你应该只使用int来代替*int8*byte

相关问题