2017-05-01 1 views
1

Je lis un gros fichier csv qui a environ 1B lignes. J'ai rencontré un problème avec l'analyse de la date. Python est lent dans le traitement.Existe-t-il un moyen d'améliorer la vitesse de la date d'analyse pour les fichiers volumineux?

une seule ligne dans le fichier ressemble à ce qui suit, '20170427,20:52:01.510,ABC,USD/MXN,1,OFFER,19.04274,9000000,[email protected]@8653948257753368229,0.0\n'

si je regarde seulement à travers les données, il faut 1 minute. Mais si j'ai essayé d'analyser la date et l'heure, cela prendra 8 minutes.

t0 = datetime.datetime.now() 
i = 0 
with open(r"D:\FxQuotes\ticks.log.20170427.txt") as file: 
    for line in file: 
     strings = line.split(",") 

     datetime.datetime(
      int(strings[0][0:4]), # %Y 
      int(strings[0][4:6]), # %m 
      int(strings[0][6:8]), # %d 
      int(strings[1][0:2]), # %H 
      int(strings[1][3:5]), # %M 
      int(strings[1][6:8]), # %s 
      int(strings[1][9:]), # %f 
     )  

     i+=1 
print(i) 
t1 = datetime.datetime.now() - t0 
print(t1) 

129908976 
0:08:13.687000 

Le split() prend environ 1 minute, et l'analyse syntaxique date prend environ 6 minutes. Y a-t-il quelque chose que je puisse faire pour améliorer cela?

+0

Vous pouvez regarder dans [gevent] (http://www.gevent.org/). Cela vous permettrait de diviser le processus entre plusieurs threads - autant que vous le souhaitez, en fait, alors faites attention aux cpu/mem caps. – Neil

+0

Devez-vous convertir la date en un objet datetime réel? – Grimmy

+0

'' line [: s.index (',')] '' pour que la date pique plus vite? ou simplement découper un index codé en dur si le format de chaque ligne est le même. '' ligne [0: 8] ''. – Grimmy

Répondre

2

@TemporalWolf avait l'excellente suggestion d'utiliser ciso8601. Je n'en ai jamais entendu parler alors j'ai pensé que je ferais un essai.

D'abord, j'ai comparé mon ordinateur portable avec votre ligne d'échantillonnage. J'ai fait un fichier CSV avec 10 millions de lignes de cette ligne exacte et il a fallu environ 6 secondes pour tout lire. L'utilisation de votre code d'analyse de date a permis d'obtenir un délai de 48 secondes, ce qui était logique car vous l'avez également signalé en prenant 8 fois plus de temps. Ensuite, j'ai réduit le fichier à 1 million de lignes et je pouvais le lire en 0,6 secondes et analyser les dates en 4,8 secondes, donc tout semblait correct.

Puis je suis passé à ciso8601 et, presque comme par magie, le temps de 1 million de lignes est passé de 4,8 secondes à environ 1,9 secondes:

import datetime 
import ciso8601 

t0 = datetime.datetime.now() 
i = 0 
with open('input.csv') as file: 
    for line in file: 
     strings = line.split(",") 
     d = ciso8601.parse_datetime('%sT%s' % (strings[0], strings[1])) 
     i+=1 
print(i) 
t1 = datetime.datetime.now() - t0 
print(t1) 

Notez que vos données sont presque au format ISO 8601 déjà . Je devais simplement coller la date et l'heure avec un "T" au milieu.

+0

Que '' split'' ajoute aussi 15% à la durée. S'il veut seulement inspecter la date, nous pouvons simplement accéder '' ligne [0: 8] '' – Grimmy

+0

va augmenter la vitesse du module csv? – eri

+0

D'après mon expérience, «% s% s»% (str1, str2) 'est l'un des moyens les plus lents de concaténer les chaînes. En fait, la concaténation directe est plus rapide dans ce cas: 'parse_datetime (chaînes [0] + '' + chaînes [1])'. De plus, 'from from ciso8601 import parse_datetime' vous évite d'avoir à rechercher la référence à chaque appel, ce qui sera plus rapide comparé à' ciso8601.parse_datetime() 'De plus, couper la chaîne (comme Grimmy) réduit le temps de moitié autre optimisation. Notez que ces comparaisons sont ** dépendantes de la version **. – TemporalWolf