2013-01-04 14 views
8

I file di dati contengono elenchi di stringhe che rappresentano le date formattate ISO. Attualmente, io li sto leggendo nel usando:Converti l'elenco dei dati in tempo reale molto lento con il tempo di Python

mydates = [ datetime.datetime.strptime(timdata[x], "%Y-%m-%dT%H:%M:%S") for x in range(len(timedata)) ] 

Questo sembra abbastanza semplice, ma è incredibilmente lento quando si opera su enormi liste di ~ 25000 calendario -> circa 0,34 secondi per la lista convertito. Dato che ho migliaia di elenchi di questo tipo, sto cercando un modo più rapido. Tuttavia, non sono riuscito a trovarne uno ancora. L'analizzatore dateutil funziona ancora peggio ...

+3

Vuoi dire che pensi di analizzare e convertire 25.000 date, compresa la costruzione di un nuovo elenco delle stesse dimensioni dovrebbe essere più veloce di un terzo di secondo in una lingua interpretata? Potresti voler passare a una lingua compilata. –

+1

@TimPietzcker È possibile leggere e analizzare un file contenente più di 25000 date e altre 10 colonne in meno di un terzo di secondo con numpy/panda. – bmu

+0

Questo è quello che ho provato anche io .... – HyperCube

risposta

8

Indexing/affettare sembra essere più veloce rispetto l'espressione regolare usata da @NPE:

In [47]: def with_indexing(dstr):        
    ....:  return datetime.datetime(*map(int, [dstr[:4], dstr[5:7], dstr[8:10], 
    ....:        dstr[11:13], dstr[14:16], dstr[17:]])) 

In [48]: p = re.compile('[-T:]') 

In [49]: def with_regex(dt_str): 
    ....:  return datetime.datetime(*map(int, p.split(dt_str))) 

In [50]: %timeit with_regex(dstr) 
100000 loops, best of 3: 3.84 us per loop 

In [51]: %timeit with_indexing(dstr) 
100000 loops, best of 3: 2.98 us per loop 

Penso che se si utilizzasse un parser di file come numpy.genfromtxt, l'argomento converters e un metodo di parsing veloce delle stringhe, è possibile leggere e analizzare un intero file in meno di mezzo secondo.

ho usato la seguente funzione per creare un file di esempio con circa 25000 righe, stringhe di data ISO come indice e 10 colonne di dati:

import numpy as np 
import pandas as pd 

def create_data(): 
    # create dates 
    dates = pd.date_range('2010-01-01T00:30', '2013-01-04T23:30', freq='H') 
    # convert to iso 
    iso_dates = dates.map(lambda x: x.strftime('%Y-%m-%dT%H:%M:%S')) 
    # create data 
    data = pd.DataFrame(np.random.random((iso_dates.size, 10)) * 100, 
         index=iso_dates) 
    # write to file 
    data.to_csv('dates.csv', header=False) 

che ho usato il seguente codice per analizzare il file:

In [54]: %timeit a = np.genfromtxt('dates.csv', delimiter=',', 
            converters={0:with_regex}) 
1 loops, best of 3: 430 ms per loop 

In [55]: %timeit a = np.genfromtxt('dates.csv', delimiter=',', 
            converters={0:with_indexing}) 
1 loops, best of 3: 391 ms per loop 

pandas (sulla base di NumPy) ha un parser di file C-based che è ancora più veloce:

In [56]: %timeit df = pd.read_csv('dates.csv', header=None, index_col=0, 
            parse_dates=True, date_parser=with_indexing) 
10 loops, best of 3: 167 ms per loop 
+0

Grazie per la risposta elaborata. Questo aiuta molto! – HyperCube

15

Ecco un modo per farlo su 3 volte più veloce.

La versione originale:

In [23]: %timeit datetime.datetime.strptime("2013-01-01T01:23:45", "%Y-%m-%dT%H:%M:%S") 
10000 loops, best of 3: 21.8 us per loop 

La versione più veloce:

In [24]: p = re.compile('[-T:]') 

In [26]: %timeit datetime.datetime(*map(int, p.split("2013-01-01T01:23:45"))) 
100000 loops, best of 3: 7.28 us per loop 

Questo è ovviamente in nessun posto vicino il più flessibile strptime().

edit: Utilizzando un unico regex per estrarre i componenti della data è marginalmente più veloce:

In [48]: pp = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})') 

In [49]: %timeit datetime.datetime(*map(int, pp.match("2013-01-01T01:23:45").groups())) 
100000 loops, best of 3: 6.92 us per loop 
+0

Grazie per la rapida risposta! 3 volte più veloce è un grande miglioramento !! :) – HyperCube