2011-04-28 15 views
5

¿Alguien sabe una forma más rápida de convertir la cadena de fecha (12-12-12 12: 21: 12.123) en número?Función más rápida que datenum en MATLAB

+0

Por número, Qué quiere decir una marca de tiempo, tales como los "segundos desde la época" a menudo se utilizan? –

Respuesta

18

A menudo es instructivo perfilar las funciones incorporadas de Matlab y extraer solo la funcionalidad interna de interés.

En su caso particular,

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

es 3 veces más rápido (se tarda 30% de las veces) que:

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

donde dtstr2dtnummx es una función interna (C: \ Archivos de programa \ Matlab \ R2011a \ toolbox \ matlab \ timefun \ private \ dtstr2dtnummx.mexw32 en mi máquina con Windows).

Para obtener acceso a esta función interna, simplemente agregue su carpeta a la ruta de Matlab usando la función addpath, o copie el archivo dtstr2dtnummx.mexw32 en otra carpeta que ya esté en su ruta de Matlab.

Tenga en cuenta que el formato de cadena es diferente entre dtstr2dtnummx y datenum, ¡así que tenga cuidado!

Para aquellos interesados, la carpeta de arriba contiene otras interesantes funciones de conversión de fechas, ¡así que explore y disfrute!

Nota 5/5/2011: ahora he publicado un artículo que amplía esta respuesta en http://undocumentedmatlab.com/blog/datenum-performance/

+0

Desafortunadamente, no puede agregar directorios privados de Matlab a la ruta, por lo que para los usuarios que no tienen la opción de copiar el archivo en su directorio actual, esta solución no funcionará. –

+0

Para aclarar, es posible que los usuarios no puedan agregar el archivo que contiene 'dtstr2dtnummx' a su directorio actual debido a problemas de derechos de autor. –

+0

@Ricardo - No creo que haya ningún problema de derechos de autor aquí. Creo que tiene derecho a usar cualquier función interna cuando compra una licencia de Matlab. –

2

A menudo es necesario tomar un enfoque de sistemas. Tuve un problema muy similar cuando extraje miles de fechas de un DB. Resulta que muchos DB modernos (Postgres, servidor Sql & Oracle son los que he probado) todos pueden hacer la conversión de sus representaciones de fecha a las representaciones de fecha de Matlab varios órdenes de magnitud más rápido que el texto a datenum en el lado de matlab. Si estos datos provienen de una base de datos, ¡piense en la conversión de la base de datos!

2

Presumiblemente, si le importa el tiempo dedicado a la conversión de fechas, está convirtiendo muchas de ellas. Incluso las optimizaciones JIT en las versiones recientes de Matlab a un lado, obtendrá resultados mucho más rápidos llamando

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

que

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

Si usted no está haciendo ya que, a empezar por ahí, ya que permite a MATLAB reduzca la sobrecarga de calcular su formato de fecha para cada llamada a la función.

0

Me doy cuenta de que esta pregunta es antigua. Sin embargo, logré hacer una función que es aproximadamente 30-40 veces más rápida que el datenum. Nota: hay fallas menores dependiendo del uso. Si alguien quiere que lo precie, solo házmelo saber.

Ejecutar en 1,792,379 filas:

  • datenum - 11.463186 segundos
  • datenumjck - 0.300503 segundos

acaba de leer su archivo con TextScan y la fecha y hora como dobles y entrada interpretan junto con la fecha formato a mi función.

Ejemplo:

Supongamos datos se formatea como los siguientes:

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 

Leer datos:

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

Especificar formato de fecha y utilizar datenumjck():

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

Código:

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 
Cuestiones relacionadas