Быстрее, чем datenum в MATLAB - PullRequest
       4

Быстрее, чем datenum в MATLAB

5 голосов
/ 28 апреля 2011

Кто-нибудь знает более быстрый способ преобразования строки даты (2010-12-12 12: 21: 12.123) в число?

Ответы [ 4 ]

18 голосов
/ 28 апреля 2011

Часто бывает полезно профилировать встроенные функции Matlab и извлекать только интересующую внутреннюю функциональность.

В вашем конкретном случае,

dtstr2dtnummx({'2010-12-12 12:21:12.123'},'yyyy-MM-dd HH:mm:ss')

в 3 раза быстрее (занимает 30% времени), чем:

datenum({'2010-12-12 12:21:12.123'},'yyyy-mm-dd HH:MM:SS')

где dtstr2dtnummx - это внутренняя функция (C: \ Program Files \ Matlab \ R2011a \ toolbox \ matlab \ timefun \ private \ dtstr2dtnummx.mexw32 на моем компьютере с Windows).

Чтобы получить доступ к этой внутренней функции, просто добавьте ее папку в путь Matlab с помощью функции addpath или скопируйте файл dtstr2dtnummx.mexw32 в другую папку, которая уже находится на вашем пути Matlab.

Обратите внимание, что формат строки между dtstr2dtnummx и datenum отличается, поэтому будьте осторожны!

Для тех, кто заинтересован, папка выше содержит другие интересные функции преобразования даты, так что изучайте и наслаждайтесь!

Примечание 5/5/2011: я опубликовал статью, которая расширяет этот ответ на http://undocumentedmatlab.com/blog/datenum-performance/

2 голосов
/ 29 марта 2014

Предположительно, если вы заботитесь о времени, потраченном на преобразование дат, вы конвертируете многие из них.Даже если не принимать во внимание JIT-оптимизацию в последних версиях matlab, вы получите гораздо более быстрые результаты, вызывающие

datenum(cellarrayofdates, 'yyyy-mm-dd HH:MM:SS');

, чем

for i=1:length(cellarrayofdates); datenum(cellarrayofdates{i}, 'yyyy-mm-dd HH:MM:SS'); end

Если вы этого еще не сделали, начните сэто позволяет matlab сократить накладные расходы на вычисление формата даты для каждого вызова функции.

2 голосов
/ 05 мая 2011

Часто требуется системный подход.У меня была очень похожая проблема, когда я извлекал тысячи дат из БД.Оказывается, что многие современные БД (Postgres, Sql server и Oracle - те, которые я пробовал), все могут выполнять преобразование из их представлений даты в представления данных Matlab на несколько порядков быстрее, чем текст в datenum на стороне matlab.Если эти данные поступают из БД, подумайте о преобразовании на стороне БД !!

0 голосов
/ 28 июля 2016

Я понимаю, что этот вопрос старый.Однако мне удалось создать функцию, которая примерно в 30-40 раз быстрее, чем datenum.Примечание: есть небольшие недостатки в зависимости от использования.Если кто-то хочет, чтобы я его префектировал, просто дайте мне знать.

Запустите 1792 379 строк:

  • datenum - 11,463186 секунд
  • datenumjck - 0,300503 секунды

Просто прочитайте ваш файл с возможностью сканирования текста и интерпретируйте дату и время как двойные и введите их вместе с форматом даты в мою функцию.

Пример:

Предположимданные форматируются следующим образом:

Data,2016-03-03,16:15:50;686,0.000000,-0.009500
Data,2016-03-03,16:15:50;696,0.000000,0.006500
Data,2016-03-03,16:15:50;706,0.000000,0.004500
Data,2016-03-03,16:15:50;716,0.000000,-0.006000

Чтение данных:

fileID = fopen('myFile.csv','r');
formatSpec = '%*s %f %f %f %f %f %f %f %*[^\n]'; % Ignore first string, save
                                                 % date and time as doubles
                                                 % ignore all other data
data = textscan(fileID,formatSpec,'delimiter',',\t/:;-.\\ ');
fclose(fileID);

Укажите формат даты и используйте datenumjck ():

dateFormat = 'yyyy-mm-dd,HH:MM:SS;FFF';
numDate = datenumjck(data,dateFormat);

Код:

function num = datenumjck(data, dateFormat)

n = size(data{1});
dateFormat = textscan(dateFormat,'%s','delimiter',',/:;-.\\');
dateFormat = dateFormat{1};

k = find(strcmp('yyyy', dateFormat),1);
if ~isempty(k)
    y = data{k};
elseif ~isempty(find(strcmp('yy', dateFormat),1))
    y = data{find(strcmp('yy', dateFormat),1)};
else
    y = zeros(n);
end

k = find(strcmp('mm', dateFormat),1);
if ~isempty(k)
    m = data{k};
elseif ~isempty(find(strcmp('mmm', dateFormat),1))
    month = cellfun(@strfind,...
        repmat({'janfebmaraprmayjunjulaugsepoctnovdec'},...
        size(data),lower(data(find(strcmp('mmm', dateFormat),1)))));
    m = (month+2)/3;
else
    m = zeros(n);
end

k = find(strcmp('dd', dateFormat),1);
if ~isempty(k)
    d = data{k};
else
    d = zeros(n);
end

k = find(strcmp('HH', dateFormat),1);
if ~isempty(k)
    H = data{k};
else
    H = zeros(n);
end

k = find(strcmp('MM', dateFormat),1);
if ~isempty(k)
    M = data{k};
else
    M = zeros(n);
end


k = find(strcmp('SS', dateFormat),1);
if ~isempty(k)
    S = data{k};
else
    S = zeros(n);
end

k = find(strcmp('FFF', dateFormat),1);
if ~isempty(k)
    F = data{k};
else
    F = zeros(n);
end

ms = [0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];

num = zeros(n);
for k = 1:n
    num(k) = y(k)*365 + ms(m(k)) + d(k) + floor(y(k)/4)...
        - floor(y(k)/100) + floor(y(k)/400) + (mod(y(k),4)~=0)...
        - (mod(y(k),100)~=0) + (mod(y(k),400)~=0)...
        + (H(k)*3600 + M(k)*60 + S(k) + F(k)/1000)/86400 + 1;
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...