0

我有一组 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-大数组)。如何合并所有这些数据以获得 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

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

谢谢!

4

1 回答 1

1

您的代码有几处错误:

首先,错误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')。

此外,这只是从每个结构中检索第一列,因此我对其进行了修改以检索 3x,y,z列。如果您真的只想要第一列,只需替换variable.(my_field) = AIS_SEC{1,k}.datavariable.(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 次循环。直观地反击这样做是为了获得更好的性能。第一遍只是计算每个结构中数据点的数量(以及标记空的数据点)。由于第一遍返回的数字,我们可以在第二遍之前预先分配输出矩阵,并将每个结构数据分配到正确位置的合并数组中,而无需在每次迭代时调整输出数组的大小。

于 2019-10-21T15:17:16.403 回答