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