#performance #matlab #csv
#Производительность #matlab #csv-файл
Вопрос:
У меня есть 3 массива, которые я хочу записать в файл csv:
dates_array — T x 1
вектор последовательных дат matlab;
наблюдения — T x N
массив числовых данных;
string_array — N x 1
вектор строк
Я хочу поместить все в массив ячеек в формате панели. Для этого я могу выполнить цикл for . Но когда T и N очень велики, это очень неэффективно;
clear all
clc
% Generate Data
T = 1000;
N = 100;
dates_array = 737791:1:737791 T-1;
dates_array = dates_array';
observations = rand(T,N);
string_array = string(char(randi([33 126],N,10)));
% Put in panel format
count = 1;
for i = 1:N
for j=1:T
out_for_csv{count,1} = {datestr(dates_array(j,1))};
out_for_csv(count,2) = {observations(j,i)};
out_for_csv(count,3) = {string_array(i,1)};
count = count 1;
end
end
Tab = cell2table(out_for_csv);
writetable(Tab,'myDataFile.csv')
Должен быть лучший способ сделать это вместо цикла. Я действительно попробовал несколько вещей, но мне всегда не удавалось собрать все воедино в out_for_csv
матрице.
Например, одним из эффективных способов получения векторов из трех столбцов является:
column1 = repmat(datestr(dates_array(j,1)),N,1);
column2 = observations(:);
column3 = repelem(string_array,T,1);
Теперь мне просто нужно выяснить, как объединить эти три столбца.
Комментарии:
1. И… в чем вопрос …? Забегая вперед, я могу очень сильно повлиять на ваши общие обстоятельства, поэтому я бы предложил следующее: 1) если вы можете сделать свои данные чисто числовыми, используйте
csvwrite
(или рекомендуемые сейчасwritematrix
; 2) если вы не можете, и ваши данные большие (например, N> 1 млн), используйтеfprintf
; 3)до более поздних версий Matlab не взаимодействуйте,table
если ваш набор данных не очень мал (N<1000).2. Между ними не используйте ячейки, если вы не вынуждены. У вас есть столбцы данных. Поэтому вставляйте столбцы
table()
напрямую.3. Этот последний комментарий делает трюк. Спасибо.
Ответ №1:
Мне удалось сократить время выполнения на моем компьютере примерно с 21 секунды до 1,5 секунды, что в 14 раз повысило скорость! Что действительно помогло ускорить процесс, так это создать большую символьную матрицу в памяти, а затем записать ее с помощью одной fprintf
команды.
Пара незначительных изменений, которые я внес в код, — это заполнение генератора случайных чисел, чтобы я получал согласованные случайные числа, чтобы я мог сравнить исходный код с моим новым кодом. Я также ограничил случайные символьные строки только прописными буквами, поскольку исходный код иногда вставлял запятую, и это приводило к несоответствующему количеству столбцов при считывании выходного файла в Excel.
Одна сложная вещь заключается в том, что когда вы записываете символ, который использует fprintf
maxtrix, вам нужно его перенести, поскольку fprintf
сначала он работает по каждому столбцу.
Вот код:
T = 1000;
N = 100;
dates_array = 737791 (0:(T-1))';
dates_array = datestr(dates_array);
% Add a comma after the dates
dates_array = [dates_array, repmat(',', T, 1)];
% Replicate the dates N times
dates_array = repmat(dates_array, N, 1);
% Seed the randon number generator to get consistent values so comparisons between versions can be made
rng(0)
observations = rand(T, N);
% convert from a matrix to a column
observations = reshape(observations, T*N, 1);
% Convert from numbers to characters
observations = num2str(observations, 5);
% Add a comma after the observations
observations = [observations, repmat(',', T*N, 1)];
% Make the matrix of strings
string_array = char(randi([65 90], 1, N * 10));
% Replicate T times
string_array = repmat(string_array, T, 1);
% Turn matrix of 10-char strings into a vector of 10-char strings
string_array = reshape(string_array, N * T, 10);
% Join the date, observations, strings, and carriage return
out = [dates_array, observations, string_array, repmat(newline, T*N, 1)];
title_row = 'col1,col2,col3';
num_extra_commas = size(out, 2) - length(title_row) - 1;
title_row = [title_row, repmat(',', 1, num_extra_commas), newline];
out = [title_row; out];
fid = fopen('myDataFileb.csv', 'wt');
fprintf(fid, '%s', out');
fclose(fid);