[Python] Accélère le chargement du fichier CSV de séries chronologiques

Lors de l'analyse de données de séries chronologiques, vous lisez souvent des données à partir de fichiers csv / tsv.

Si le fichier a une capacité de quelques dizaines de Mo, vous ne vous en souciez peut-être pas autant, mais s'il s'agit d'un fichier de quelques centaines de Mo, il faut quelques secondes à quelques dizaines de secondes juste pour le lire, et cela prend de quelques secondes à quelques dizaines de secondes, ce qui se produit chaque fois que vous exécutez le code. Le temps devient stressant.

Ici, nous allons introduire une méthode qui peut exploser le processus de lecture avec un peu d'ingéniosité.

Environnement d'exécution

Mesurez le temps d'exécution avec le MBP à portée de main.

MacBook Pro (Retina, 13-inch, Mid 2014)

De plus, l'environnement d'exécution du code de mesure est la dernière version de la série 2.7.

$ python --version
$ Python 2.7.10

Utilisez le module pandas pour lire le fichier csv.

>>> import pandas
>>> pandas.__version__
0.18.1

Le fichier csv à lire utilise les données du taux de change dollar-yen par incréments d'une minute de 2005 à 2015 qui étaient à portée de main. Contient des données dans 5 colonnes de temps, prix d'ouverture, prix élevé, prix bas et prix de clôture x 3687221 lignes.

Le contenu est comme ça

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

C'est un fichier csv d'environ 204 Mo.

0 ・ Préparation

Utilisez la méthode «time» du module «time» standard pour mesurer le temps. J'ai préparé le code suivant comme préparation à cela.

La méthode calctime est une méthode de mesure simple qui exécute une expression arbitraire et renvoie la différence entre l'heure de début et l'heure de fin.

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}

1. Lisez normalement

Tout d'abord, pour mesurer le temps de référence, utilisez la méthode read_csv pour mesurer le temps.

calctime.py


import pandas

csv = calctime(lambda: pandas.read_csv('usdjpy-1m.csv'))
print('Lire normalement_csv{}Ça a pris une seconde'.format(csv['time']))
Lire normalement_csv 7.56608009338 a pris 2 secondes

Cela prend 7,5 secondes. De plus, comme le fichier traité cette fois-ci est des données de séries chronologiques, j'analyserai également la colonne qui stocke l'heure dans le type datetime.

calctime.py


import pandas

csv = calctime(lambda: pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time'))
print('lire en analysant la colonne de temps_csv{}Ça a pris une seconde'.format(csv['time']))
lire en analysant la colonne de temps_40 avec csv.0371601582 Cela a pris 2 secondes

Cela prend 40 secondes. Je ne peux pas parler d'attendre 40 secondes à chaque fois, alors accélérons.

2. Sérialisez l'objet

Python est livré en standard avec un module appelé «pickle» qui sérialise les objets en mémoire en octets.

En tant que nom du système singulier de Pickles, il fournit une fonction pour convertir un objet à court terme en mémoire en une forme qui peut être sortie dans un fichier et l'enregistrer dans le stockage. Les légumes crus peuvent également être marinés et stockés pendant une longue période.

Le code ressemble à ceci.

Enregistrez l'objet une fois stocké dans la variable avec pandas.read_csv comme usdjpy-1m.csv.pkl en utilisant pickle.dump sur le stockage, et lisez la chaîne d'octets vidés en utilisant pickle.load. Je mesure le temps.

calctime.py


import pandas
import pickle

#Chargement de csv
csv = pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time')

#Vider les octets dans le fichier
pickle.dump(csv, open('usdjpy-1m.csv.pkl', 'w'))

#Recharger le fichier sauvegardé
pickled = calctime(lambda: pickle.load(open('usdjpy-1m.csv.pkl', 'w')))
print('Lors du chargement avec cornichon{}Ça a pris une seconde'.format(pickled['time']))
5 lors du chargement avec cornichon.65008401871 a pris 1 seconde

Il a été considérablement réduit de 40 secondes à 5,6 secondes.

Il semble que cela fonctionne car il n'est plus nécessaire d'analyser le type datetime à chaque fois.

Une fois que vous l'avez vidé avec pickle, vous pouvez l'utiliser comme un objet pandas en le lisant la prochaine fois, donc c'est facile. J'ai fait beaucoup de progrès.

Mais c'est assez long pour attendre 5,6 secondes à chaque fois. Rendons ce cornichon encore plus rapide.

3. Spécifiez le protocole de pickle

Comme indiqué dans http://docs.python.jp/2/library/pickle.html#pickle.dump , Pickle peut spécifier le protocole à utiliser lors du déchargement.

Il existe des versions 0 à 2 du protocole, 0 étant la plus ancienne et la plus lente et 2 la plus récente et la plus rapide. La version 2 ne peut être utilisée que dans les environnements Python 2.3 ou supérieur et a la particularité de ne pas être rétrocompatible.

Et la valeur par défaut est la version 0. Si vous utilisez pickle.dump sans rien spécifier, vous finissez par utiliser un protocole lent au lieu d'une compatibilité descendante.

Spécifions le protocole dans le code ci-dessus et réexécutons.

calctime.py


import pandas
import pickle

#Chargement de csv
csv = pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time')

#Vider les octets dans un fichier à l'aide du protocole de la version 2
pickle.dump(csv, open('usdjpy-1m.csv.pkl', 'w'), protocol=2)

#Recharger le fichier sauvegardé
pickled = calctime(lambda: pickle.load(open('usdjpy-1m.csv.pkl', 'w')))
print('Avec la version 2{}Ça a pris une seconde'.format(pickled['time']))
1 avec la version 2.07643604279 Cela a pris 2 secondes

5,6 secondes → Elle a été raccourcie à environ 1 seconde. Vous pouvez maintenant lire à une vitesse agréable.

Mais je ne suis toujours pas satisfait. Attendre 1 seconde à chaque fois est stressant.

Enfin, ajoutons un autre effort pour exploser le code.

4. Enregistrer le cornichon dans redis

Si vous enregistrez la chaîne d'octets sauvegardée par pickle en tant que fichier sur le stockage, il faudra un certain temps pour la lire.

À l'inverse, le fait que le temps d'accès au stockage soit un goulot d'étranglement signifie qu'il doit être éliminé.

Ici, changeons la destination de sauvegarde en redis, qui enregistre les données en mémoire au lieu de stockage.

redis est une base de données de type magasin clé-valeur qui fonctionne en mémoire et a la particularité d'être extrêmement rapide car elle stocke des données en mémoire.

La méthode d'installation détaillée et l'explication sont omises ici, veuillez donc la vérifier si vous êtes intéressé.

Si l'installation réussit, redis fonctionne-t-il correctement?

$ redis-cli ping
PONG

Vous pouvez vérifier en tapant la commande.

Pour accéder à redis depuis python, installez le module redis avec pip.

$ pip install redis

Modifions un peu le code précédent, sauvegardons le csv lu en tant que chaîne d'octets à vider et redis, puis mesurons le temps pour l'obtenir à partir de redis.

Cette fois, ni le vidage ni le chargement ne sont effectués en spécifiant un fichier, mais nous voulons l'étendre à une variable, donc les méthodes utilisées sont pickle.dumps et pickle.loads.

calctime.py


import pandas
import pickle
import redis

#Chargement de csv
csv = pandas.read_csv('usdjpy-1m.csv', parse_dates=['time'], index_col='time')

#Vider les octets à l'aide du protocole de la version 2
dumped = pickle.dumps(csv, protocol=2)

#Enregistrez la chaîne d'octets vidée dans redis
r = redis.Redis(host='localhost', port=6379, db=0)
r.set('usdjpy-1m.csv', dumped)

#Lire les octets de redis et restaurer avec pickle
csv = calctime(lambda: pickle.loads(r.get('usdjpy-1m.csv')))
print('Avec redis{}Ça a pris une seconde'.format(csv['time']))
0 avec redis.Cela a pris 332698106766 secondes

Il a été réduit de 1 seconde à 0,33 seconde.

Avec cela, vous pouvez exécuter le code sans aucun stress! Par rapport aux 40 premières secondes de chargement, il était 121 fois plus rapide.

prime

Voici l'ensemble de code utilisé dans l'expérience.

calctime.py


#!/usr/bin/python
# -*- encoding: utf-8 -*-

import pandas
import pickle
import redis
from time import time

#Méthode de mesure du temps
def calctime(func):
	start = time()
	r = func()
	return {'value': r, 'time': time()-start}

#chemin du fichier csv
csv_filepath = 'usdjpy-1m.csv'

#Lire normalement
read_csv = calctime(lambda: pandas.read_csv(csv_filepath, parse_dates=['time'], index_col='time'))
print('Lire normalement_csv{}Ça a pris une seconde'.format(read_csv['time']))

#pickle Lire à l'aide de Protocolol version 0
pickle.dump(read_csv['value'], open('csv0.pkl', 'w'))
pickle_load_0 = calctime(lambda: pickle.load(open('csv0.pkl', 'r')))
print('pickle avec Protocolol Version 0{}Ça a pris une seconde'.format(pickle_load_0['time']))

#pickle Lire avec 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('Avec pickle Protocolol Version 2{}Ça a pris une seconde'.format(pickle_load_2['time']))

#Lire à l'aide de 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('Avec redis{}Ça a pris une seconde'.format(redis_get['time']))

finalement

Lors de l'analyse des données, je pense qu'il existe de nombreuses situations dans lesquelles vous devez exécuter le code plusieurs fois et répéter des essais et des erreurs, mais j'espère que cela vous aidera à faire pivoter les itérations aussi efficacement que possible dans de tels cas.

L'auteur publie quotidiennement des informations techniques sur Twitter. Je vous serais reconnaissant si vous pouviez me suivre.

https://twitter.com/YuhsakInoue

Recommended Posts

[Python] Accélère le chargement du fichier CSV de séries chronologiques
Python: analyse des séries chronologiques
Question sur la série chronologique Python
Tracer CSV de données de séries temporelles avec une valeur unixtime en Python (matplotlib)
[Python] Tracer des données de séries chronologiques
Accélérer le chargement des images Python
[Python] Chargement de fichiers csv à l'aide de pandas
Calcul de la fidélité des clients dans les séries chronologiques
Python: analyse des séries chronologiques: prétraitement des données des séries chronologiques
Diviser timedelta dans la série Python 2.7
L'intrigue de séries temporelles a commencé ~ édition python ~
Différenciation des données de séries chronologiques (discrètes)
Analyse des séries chronologiques 3 Prétraitement des données des séries chronologiques
Analyse des séries chronologiques 4 Construction du modèle SARIMA
Grammaire de base de la série Python3 (liste, tapple)
Introduction facile de la série python3 et d'OpenCV3
Python: analyse des séries temporelles: création d'un modèle SARIMA
Obtenez des données de séries chronologiques de k-db.com avec Python
Premier Python
mesure du temps
Python: Analyse des séries temporelles: Constantity, modèle ARMA / ARIMA
Décomposition des séries temporelles
Encodage de caractères lors de l'utilisation du module csv de python 2.7.3
Bases de python ①
Premier Python
Lissage des séries temporelles et des données de forme d'onde 3 méthodes (lissage)
Copie de python
Voir les détails des données de séries chronologiques dans Remotte
CSV en Python
Au moment de la mise à jour de python avec ubuntu
Créez une carte chronologique animée de l'état de l'infection par le virus corona avec python + plotly
Évaluation de la vitesse de sortie du fichier CSV en Python
Exemple de lecture et d'écriture de CSV avec Python
Introduction de Python
Fonctionnement de base de Python Pandas Series et Dataframe (1)
Implémentation de la méthode de clustering k-shape pour les données de séries chronologiques [Apprentissage non supervisé avec python Chapitre 13]
Traitement pleine largeur et demi-largeur des données CSV en Python
Résumé du tri Python (liste, type de dictionnaire, série, DataFrame)
Python 3.4 Créer un environnement Windows7-64bit (pour l'analyse des séries chronologiques financières)
Détection d'anomalies des données de séries chronologiques par LSTM (Keras)
Enregistrer les séries chronologiques TOPIX au format pickle, csv, Excel
[Série chronologique avec plotly] Visualisation dynamique avec plotly [python, cours boursier]
[Python] Opération d'énumération
Liste des modules python
Temps d'exécution de la fonction (Python)
Unification de l'environnement Python
Copie des préférences python
Principes de base du grattage Python
[python] comportement d'argmax
"Analyse des séries chronologiques de mesure des données économiques et financières" Résolution du problème de fin de chapitre avec Python
Utilisation des locaux Python ()
le zen de Python
Installation de Python 3.3 rc1
Analyse des séries chronologiques RNN_LSTM1
Analyse des séries chronologiques 1 Principes de base
Sortie du temps d'exécution de python
Comment calculer la somme ou la moyenne des données csv de séries chronologiques en un instant
Fonction de plancher de temps (Python)