Bei der Analyse von Zeitreihendaten lesen Sie häufig Daten aus CSV / TsV-Dateien.
Wenn die Datei eine Kapazität hat, die in einige zehn MB passt, ist es Ihnen vielleicht egal, aber wenn es sich um eine Datei mit einigen hundert MB handelt, dauert das Lesen nur einige Sekunden bis einige zehn Sekunden, und jedes Mal, wenn Sie den Code ausführen, dauert es einige Sekunden bis einige zehn Sekunden. Die Zeit wird stressig.
Hier werden wir eine Methode vorstellen, die den Lesevorgang mit ein wenig Einfallsreichtum explodieren lässt.
Messen Sie die Ausführungszeit mit dem vorliegenden MBP.
MacBook Pro (Retina, 13-inch, Mid 2014)
Darüber hinaus ist die Ausführungsumgebung des Messcodes die neueste Version der 2.7-Serie.
$ python --version
$ Python 2.7.10
Verwenden Sie das Pandas-Modul, um die CSV-Datei zu lesen.
>>> import pandas
>>> pandas.__version__
0.18.1
Die zu lesende CSV-Datei verwendet die Daten des Dollar-Yen-Wechselkurses in Schritten von 1 Minute von 2005 bis 2015, die gerade zur Hand waren. Enthält Daten in 5 Zeitspalten, offenen Preis, hohen Preis, niedrigen Preis und Schlusspreis x 3687221 Zeilen.
Der Inhalt ist so
time | open | high | low | close |
---|---|---|---|---|
2005-01-03 03:00:00 | 102.360 | 102.390 | 102.360 | 102.390 |
$ wc -c < usdjpy-1m.csv
204760049
Es ist eine CSV-Datei von etwa 204 MB.
Verwenden Sie die "Zeit" -Methode des Standardmoduls "Zeit", um die Zeit zu messen. Ich habe den folgenden Code vorbereitet, um mich darauf vorzubereiten.
Die calctime
Methode ist eine einfache Messmethode, die einen beliebigen Ausdruck ausführt und die Differenz zwischen der Startzeit und der Endzeit zurückgibt.
calctime.py
#!/usr/bin/python
# -*- encoding: utf-8 -*-
from time import time
def calctime(func):
start = time()
r = func()
return {'value': r, 'time': time()-start}
Verwenden Sie zum Messen der Referenzzeit zunächst die Methode "read_csv", um die Zeit zu messen.
calctime.py
import pandas
csv = calctime(lambda: pandas.read_csv('usdjpy-1m.csv'))
print('Normal lesen_csv{}Es dauerte eine Sekunde'.format(csv['time']))
Normal lesen_CSV 7.56608009338 dauerte 2 Sekunden
Es dauert 7,5 Sekunden. Da es sich bei der diesmal behandelten Datei um Zeitreihendaten handelt, analysiere ich außerdem die Spalte, in der die Zeit gespeichert ist, nach dem Datum / Uhrzeit-Typ.
calctime.py
import pandas
csv = calctime(lambda: pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time'))
print('Lesen Sie, während Sie die Zeitspalte analysieren_csv{}Es dauerte eine Sekunde'.format(csv['time']))
Lesen Sie, während Sie die Zeitspalte analysieren_40 mit csv.0371601582 Es dauerte 2 Sekunden
Es dauert 40 Sekunden. Ich kann nicht davon sprechen, jedes Mal 40 Sekunden zu warten, also beschleunigen wir es.
Python wird standardmäßig mit einem Modul namens "pickle" geliefert, das Objekte im Speicher in Bytes serialisiert.
Als Name des singulären Systems von Pickles bietet es eine Funktion zum Konvertieren eines Kurzzeitobjekts im Speicher in eine Form, die in eine Datei ausgegeben und im Speicher gespeichert werden kann. Rohes Gemüse kann auch eingelegt und lange gelagert werden.
Der Code sieht so aus.
Speichern Sie das in der Variablen gespeicherte Objekt mit pandas.read_csv
als usdjpy-1m.csv.pkl mit pickle.dump
im Speicher und lesen Sie die Dumped-Byte-Zeichenfolge mit pickle.load
. Ich messe die Zeit.
calctime.py
import pandas
import pickle
#Laden von csv
csv = pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time')
#Bytes in Datei sichern
pickle.dump(csv, open('usdjpy-1m.csv.pkl', 'w'))
#Laden Sie die abgelegte Datei neu
pickled = calctime(lambda: pickle.load(open('usdjpy-1m.csv.pkl', 'w')))
print('Beim Laden mit Gurke{}Es dauerte eine Sekunde'.format(pickled['time']))
5 beim Laden mit Gurke.65008401871 dauerte 1 Sekunde
Es wurde stark von 40 Sekunden auf 5,6 Sekunden reduziert.
Es scheint, dass es funktioniert, da es nicht mehr erforderlich ist, den Datum / Uhrzeit-Typ jedes Mal zu analysieren.
Sobald Sie es mit Gurke entsorgt haben, können Sie es als Pandas-Objekt verwenden, indem Sie es beim nächsten Mal lesen, sodass es einfach ist. Ich habe große Fortschritte gemacht.
Aber es ist lang genug, um jedes Mal 5,6 Sekunden zu warten. Lassen Sie uns diese Gurke noch schneller machen.
Wie in [http://docs.python.jp/2/library/pickle.html#pickle.dump] gezeigt (http://docs.python.jp/2/library/pickle.html#pickle.dump) , Pickle kann das Protokoll angeben, das beim Dumping verwendet werden soll.
Es gibt die Versionen 0 bis 2 des Protokolls, wobei 0 die älteste und langsamste und 2 die neueste und schnellste ist. Version 2 kann nur in Python 2.3 oder höheren Umgebungen verwendet werden und hat die Funktion, nicht abwärtskompatibel zu sein.
Und die Standardeinstellung ist Version 0. Wenn Sie "pickle.dump" verwenden, ohne etwas anzugeben, verwenden Sie am Ende ein langsames Protokoll anstelle der Abwärtskompatibilität.
Geben Sie das Protokoll im obigen Code an und führen Sie es erneut aus.
calctime.py
import pandas
import pickle
#Laden von csv
csv = pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time')
#Speichern Sie Bytes mithilfe des Protokolls der Version 2 in die Datei
pickle.dump(csv, open('usdjpy-1m.csv.pkl', 'w'), protocol=2)
#Laden Sie die abgelegte Datei neu
pickled = calctime(lambda: pickle.load(open('usdjpy-1m.csv.pkl', 'w')))
print('Mit Version 2{}Es dauerte eine Sekunde'.format(pickled['time']))
1 mit Version 2.07643604279 Es dauerte 2 Sekunden
5,6 Sekunden → Es wurde auf ca. 1 Sekunde verkürzt. Sie können jetzt mit einer schönen Geschwindigkeit lesen.
Aber ich bin immer noch nicht zufrieden. Jedes Mal 1 Sekunde zu warten ist stressig.
Fügen wir zum Schluss noch einen weiteren Versuch hinzu, um den Code zu explodieren.
Wenn Sie die von pickle ausgegebene Byte-Zeichenfolge als Datei im Speicher speichern, dauert das Lesen einige Zeit.
Umgekehrt bedeutet die Tatsache, dass die Zugriffszeit auf den Speicher ein Engpass ist, dass sie beseitigt werden sollte.
Hier ändern wir das Speicherziel in redis, wodurch Daten im Speicher anstatt im Speicher gespeichert werden.
redis ist eine Datenbank mit Schlüsselwertspeichertyp, die im Arbeitsspeicher ausgeführt wird und die Eigenschaft hat, extrem schnell zu sein, da sie Daten im Arbeitsspeicher speichert.
Detaillierte Installationsmethoden und Erklärungen werden hier weggelassen. Bitte überprüfen Sie sie, wenn Sie interessiert sind.
Funktioniert redis bei erfolgreicher Installation ordnungsgemäß?
$ redis-cli ping
PONG
Sie können dies überprüfen, indem Sie den Befehl eingeben.
Um von Python aus auf Redis zuzugreifen, installieren Sie das Modul "Redis" mit pip.
$ pip install redis
Lassen Sie uns den vorherigen Code ein wenig ändern, die gelesene CSV als Byte-Zeichenfolge zum Speichern und Redis speichern und dann die Zeit messen, um sie von Redis abzurufen.
Dieses Mal wird weder Dump noch Laden durch Angabe einer Datei ausgeführt, aber ich möchte sie zu einer Variablen erweitern, sodass die verwendeten Methoden "pickle.dumps" und "pickle.loads" sind.
calctime.py
import pandas
import pickle
import redis
#Laden von csv
csv = pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time')
#Dump-Bytes mit dem Protokoll der Version 2
dumped = pickle.dumps(csv, protocol=2)
#Speichern Sie die ausgegebene Byte-Zeichenfolge in redis
r = redis.Redis(host='localhost', port=6379, db=0)
r.set('usdjpy-1m.csv', dumped)
#Lesen Sie die Bytes von Redis und stellen Sie sie mit pickle wieder her
csv = calctime(lambda: pickle.loads(r.get('usdjpy-1m.csv')))
print('Mit Redis{}Es dauerte eine Sekunde'.format(csv['time']))
0 mit Redis.Es dauerte 332698106766 Sekunden
Es wurde von 1 Sekunde auf 0,33 Sekunden reduziert.
Damit können Sie den Code stressfrei ausführen! Im Vergleich zu den ersten 40 Sekunden des Ladens war es 121-mal schneller.
Hier ist der im Experiment verwendete Codesatz.
calctime.py
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import pandas
import pickle
import redis
from time import time
#Zeitmessmethode
def calctime(func):
start = time()
r = func()
return {'value': r, 'time': time()-start}
#CSV-Dateipfad
csv_filepath = 'usdjpy-1m.csv'
#Normal lesen
read_csv = calctime(lambda: pandas.read_csv(csv_filepath, parse_dates=['time'], index_col='time'))
print('Normal lesen_csv{}Es dauerte eine Sekunde'.format(read_csv['time']))
#pickle Mit Protocolol Version 0 lesen
pickle.dump(read_csv['value'], open('csv0.pkl', 'w'))
pickle_load_0 = calctime(lambda: pickle.load(open('csv0.pkl', 'r')))
print('Gurke mit Protocolol Version 0{}Es dauerte eine Sekunde'.format(pickle_load_0['time']))
#pickle Read mit Protocolol Version 2
pickle.dump(read_csv['value'], open('csv2.pkl', 'w'), protocol=2)
pickle_load_2 = calctime(lambda: pickle.load(open('csv2.pkl', 'r')))
print('Mit pickle Protocolol Version 2{}Es dauerte eine Sekunde'.format(pickle_load_2['time']))
#Lesen Sie mit Redis
r = redis.Redis(host='localhost', port=6379, db=0)
r.set(csv_filepath, pickle.dumps(read_csv['value'], protocol=2))
redis_get = calctime(lambda: pickle.loads(r.get(csv_filepath)))
print('Mit Redis{}Es dauerte eine Sekunde'.format(redis_get['time']))
Ich denke, dass es bei der Analyse von Daten viele Situationen gibt, in denen Sie den Code viele Male ausführen und Versuche und Fehler wiederholen müssen, aber ich hoffe, dass es Ihnen dabei hilft, die Iterationen in solchen Fällen so effizient wie möglich zu drehen.
Der Autor veröffentlicht täglich technische Informationen auf Twitter. Ich wäre Ihnen dankbar, wenn Sie mir folgen könnten.
https://twitter.com/YuhsakInoue
Recommended Posts