在 Matlab 中合并来自 xyz 文件的所有数据

Merge all data from xyz files in Matlab

我有一组 501 个 XYZ 文件,我将其加载为

for k = 1:501

    % AIS SEC data

    AIS_SEC{k} = importdata(['AIS_SEC(' num2str(k) ').xyz']);

end

这会生成一个 1x501 元胞数组,其中存储了所有数据(我在 https://nl.mathworks.com/matlabcentral/answers/486579-how-to-merge-multiple-xyz-files-into-1-large-array 的附件中上传了此文件)。如何将所有这些数据合并为 1 个大的 XYZ 文件?最终目标是拥有一个 nx3 数组,其中来自单独 xyz 文件的所有数据都合并到 1.

比如为了集中X数据,我试过:

for k = 1:501
    my_field = sprintf('X%d', k);
    variable.(my_field) = ([AIS_SEC{1,k}.data(:,1)]);
end

但是:这种类型的变量不支持点索引。

谢谢!

你的代码有几处错误:

首先,错误 Struct contents reference from a non-struct array object. 首先出现在索引 k=33 处,因为导入的结构没有 data 字段(导入可能为空或失败)。

检查字段是否存在让代码 运行 完成。然后你会注意到你有 8 行是空的。

load('AIS_SEC.mat')
n=numel(AIS_SEC) ;
EmptyRows = false(n,1) ;
for k = 1:n
    my_field = sprintf('X%03d', k);
    if isfield( AIS_SEC{1,k} , 'data')
        variable.(my_field) = AIS_SEC{1,k}.data;
    else
        variable.(my_field) = [] ;
        EmptyRows(k) = true ;
    end
end
fprintf('Number of empty rows encountered: %u\n',sum(EmptyRows))

我也冒昧地删除了不必要的括号,添加了一个空行索引计数器,并调整了 sprintf 输出格式,以便您的所有字段都具有相同的长度(即使是第一个字段也会有前导零。'X001' to 'X500' 而不是 'X1' to 'X500').

此外,这只是从每个结构中检索第一列,所以我修改它以检索 3 x,y,z 列。如果您真的只想要第一列,只需将 variable.(my_field) = AIS_SEC{1,k}.data 替换为 variable.(my_field) = AIS_SEC{1,k}.data(:,1)


现在,这会为您提供一个包含 500 个字段(每个字段代表一个导入变量)的长结构。你的问题在这一点上还不够清楚,但如果你想拥有一个合并所有值的数组,那么你有 2 个选项:

1) 在上面的代码之后,直接将您的结构转换为合并数组:

vararray = cell2mat(struct2cell(variable)) ;

2)如果上面的步骤(最后的variable结构)不是你需要保留的,那么你可以在第一时间避免它:

load('AIS_SEC.mat')
n = numel(AIS_SEC) ;        % number of field to import

% first pass we count how many data point (if any) each structure has
EmptyRows = false(n,1) ;    
npts      = zeros(n,1) ;
for k = 1:n
    if isfield( AIS_SEC{1,k} , 'data')
        npts(k) = size( AIS_SEC{1,k}.data , 1 ) ;
    else
        EmptyRows(k) = true ;
    end
end
% fprintf('Number of empty rows encountered: %u\n',sum(EmptyRows))

% The above allows us to preallocate the output matrix at the right size
cumpts = cumsum(npts) ;
totalNumberOfPoints = cumpts(end) ;
vararray = zeros(totalNumberOfPoints,3) ;

% first field to import
vararray( 1:cumpts(1) , : ) =  AIS_SEC{1,1}.data ;
% now all the remaining ones
for k =  2:n
    idx = (cumpts(k-1)+1):cumpts(k) ;
    if ~isempty(idx)
        vararray(idx,:) = AIS_SEC{1,k}.data ;
    end
end

在这个版本中,整个结构有 2 次循环。与直觉相反,这样做是为了获得更好的性能。第一遍只是计算每个结构中数据点的数量(同时标记空的)。由于第一遍返回的数字,我们可以在第二遍之前预先分配输出矩阵,并将每个结构数据分配到正确位置的合并数组,而无需在每次迭代时调整输出数组的大小。