Эффективная запись CSV-файла из matlab

#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);