Convierte la lista de datestrings a datetime muy lenta con Python strptime

Tengo archivos de datos que contienen listas de cadenas que representan fechas con formato ISO. Actualmente, los estoy leyendo en uso:

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

Esto parece bastante sencillo, pero es ridículamente lento cuando se opera en listas enormes de ~ 25000 fechas -> aproximadamente 0,34 segundos por lista convertida. Como tengo miles de listas de este tipo, busco una manera más rápida. Sin embargo, no pude encontrar uno todavía. El analizador dateutil realiza aún peor …

La indexación / segmentación parece ser más rápida que la expresión regular utilizada por @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 

Creo que si usara un analizador de archivos como numpy.genfromtxt , el argumento de los converters y un método rápido de análisis de cadenas, puede leer y analizar un archivo completo en menos de medio segundo.

Utilicé la siguiente función para crear un archivo de ejemplo con aproximadamente 25000 filas, cadenas de fecha ISO como índice y 10 columnas de datos:

 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) 

Que utilicé el siguiente código para analizar el archivo:

 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 (basado en numpy) tiene un analizador de archivos basado en C que es aún más rápido:

 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 

Aquí hay una manera de hacerlo aproximadamente 3 veces más rápido.

La versión original:

 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 versión más rápida:

 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 

Esto obviamente no es tan flexible como strptime() .

edición: el uso de una sola expresión regular para extraer los componentes de la fecha es ligeramente más rápido:

 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