Объединить все данные из файлов XYZ в Matlab - PullRequest
0 голосов
/ 21 октября 2019

У меня есть набор из 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

НО: индексирование точек не поддерживается для переменных этого типа.

Спасибо!

1 Ответ

1 голос
/ 21 октября 2019

В вашем коде есть несколько неправильных вещей:

Во-первых, ошибка 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 прохода петли через структуру. Интуитивно против, это сделано для лучшей производительности. Первый проход предназначен только для подсчета количества точек данных в каждой структуре (а также для отметки пустых точек). Благодаря числу, возвращаемому при первом проходе, мы можем предварительно выделить матрицу вывода перед вторым проходом и назначить все данные структуры объединенному массиву в нужном месте без необходимости изменять размер выходного массива на каждой итерации.

...