web-dev-qa-db-fra.com

Comment stocker un cadre de données à l'aide de pandas

À l'heure actuelle, j'importe une CSV assez grande en tant que cadre de données chaque fois que j'exécute le script. Existe-t-il une bonne solution pour garder ce cadre de données constamment disponible entre les exécutions afin que je n'ai pas à passer tout ce temps à attendre l'exécution du script?

205
jeffstern

Le moyen le plus simple est de pickle it en utilisant to_pickle :

df.to_pickle(file_name)  # where to save it, usually as a .pkl

Ensuite, vous pouvez le recharger en utilisant:

df = pd.read_pickle(file_name)

Remarque: avant la version 0.11.1, save et load étaient le seul moyen de procéder (elles sont maintenant déconseillées en faveur de to_pickle et read_pickle).


Un autre choix courant consiste à utiliser HDF5 ( pytables ) qui offre très rapidement temps d'accès pour les grands ensembles de données:

store = HDFStore('store.h5')

store['df'] = df  # save it
store['df']  # load it

Des stratégies plus avancées sont discutées dans le livre de recettes .


Depuis 0.13, il y a aussi msgpack qui peut être meilleur pour l'interopérabilité, comme alternative plus rapide au JSON ou si vous avez des données python-objet/text-heavy (voir cette question ).

336
Andy Hayden

Bien qu'il y ait déjà quelques réponses, j'ai trouvé une comparaison intéressante dans laquelle ils ont essayé plusieurs façons de sérialiser Pandas DataFrames: Stocker efficacement les Pandas DataFrames

Ils comparent:

  • pickle: format de données d'origine ASCII
  • cPickle, une bibliothèque en C
  • pickle-p2: utilise le nouveau format binaire
  • json: librairie json standardlib
  • json-no-index: comme json, mais sans index
  • msgpack: alternative JSON binaire
  • CSV
  • hdfstore: format de stockage HDF5

Dans leur expérience, ils sérialisent un DataFrame de 1 000 000 lignes avec les deux colonnes testées séparément: une avec des données de texte, l'autre avec des nombres. Leur disclaimer dit:

Vous ne devez pas croire que ce qui suit se généralise à vos données. Vous devriez examiner vos propres données et exécuter vous-même des tests de performance.

Le code source du test auquel ils font référence est disponible en ligne . Comme ce code ne fonctionnait pas directement, j'ai apporté quelques modifications mineures, que vous pouvez obtenir ici: serialize.py J'ai eu les résultats suivants:

time comparison results

Ils mentionnent également qu'avec la conversion de données texte en données catégoriques , la sérialisation est beaucoup plus rapide. Dans leur test environ 10 fois plus rapide (voir aussi le code de test).

Edit: le format de données utilisé peut expliquer les temps de pickle supérieurs à ceux de csv. Par défaut, pickle utilise une représentation imprimable ASCII, qui génère des jeux de données plus volumineux. Comme on peut le voir sur le graphique, le pickle utilisant le nouveau format de données binaires (version 2, pickle-p2) a des temps de chargement beaucoup plus courts.

Quelques autres références:

68
agold

Si je comprends bien, vous utilisez déjà pandas.read_csv(), mais vous souhaitez accélérer le processus de développement afin que vous n'ayez pas à charger le fichier à chaque fois que vous modifiez votre script, est-ce exact? J'ai quelques recommandations:

  1. vous pouvez charger seulement une partie du fichier CSV en utilisant pandas.read_csv(..., nrows=1000) pour ne charger que le bit le plus haut de la table, pendant que vous faites le développement

  2. utilisez ipython pour une session interactive, telle que vous gardiez la table pandas en mémoire lorsque vous modifiez et rechargez votre script.

  3. convertir le csv en un table HDF5

  4. updated utilise DataFrame.to_feather() et pd.read_feather() pour stocker des données dans un format binaire feather compatible avec R très rapide (entre mes mains, légèrement plus rapide que pandas.to_pickle() pour les données numériques et beaucoup plus rapide pour les données de chaîne).

Vous pourriez également être intéressé par cette réponse sur stackoverflow.

28
Noah

Pickle fonctionne bien!

import pandas as pd
df.to_pickle('123.pkl')    #to save the dataframe, df to 123.pkl
df1 = pd.read_pickle('123.pkl') #to load 123.pkl back to the dataframe df
17

Les Pandas DataFrames ont la fonction to_pickle qui est utile pour enregistrer un DataFrame:

import pandas as pd

a = pd.DataFrame({'A':[0,1,0,1,0],'B':[True, True, False, False, False]})
print a
#    A      B
# 0  0   True
# 1  1   True
# 2  0  False
# 3  1  False
# 4  0  False

a.to_pickle('my_file.pkl')

b = pd.read_pickle('my_file.pkl')
print b
#    A      B
# 0  0   True
# 1  1   True
# 2  0  False
# 3  1  False
# 4  0  False
4
mgoldwasser

Vous pouvez utiliser un fichier de format de plume. C'est extrêmement rapide.

df.to_feather('filename.ft')
3
Huanyu Liao

Comme déjà mentionné, il existe différentes options et formats de fichier ( HDF5 , JSON , CSV , parquet , SQL ) pour stocker un trame de données. Cependant, pickle n'est pas un citoyen de première classe (selon votre configuration), car:

1) pickle est un risque potentiel pour la sécurité. Former la documentation Python pour pickle :

Avertissement Le module pickle n'est pas sécurisé contre les données erronées ou mal construites. Ne supprimez jamais les données reçues d'une source non fiable ou non authentifiée.

2) pickle est lent. Trouvez ici et ici points de repère.

En fonction de votre configuration/utilisation, les deux limitations ne s'appliquent pas, mais je ne recommanderais pas pickle comme persistance par défaut pour les trames de données pandas.

3
Michael Dorner

Les formats de fichier Numpy sont assez rapides pour les données numériques

Je préfère utiliser les fichiers numpy car ils sont rapides et faciles à utiliser ..__ Voici un repère simple pour enregistrer et charger une trame de données avec 1 colonne de 1 million de points.

import numpy as np
import pandas as pd

num_dict = {'voltage': np.random.Rand(1000000)}
num_df = pd.DataFrame(num_dict)

en utilisant la fonction magique %%timeit de ipython

%%timeit
with open('num.npy', 'wb') as np_file:
    np.save(np_file, num_df)

la sortie est 

100 loops, best of 3: 5.97 ms per loop

charger les données dans un cadre de données

%%timeit
with open('num.npy', 'rb') as np_file:
    data = np.load(np_file)

data_df = pd.DataFrame(data)

la sortie est

100 loops, best of 3: 5.12 ms per loop

PAS MAL!

LES INCONVÉNIENTS

Il y a un problème si vous enregistrez le fichier numpy à l'aide de python 2 puis essayez d'ouvrir à l'aide de python 3 (ou inversement).

2
mark jay

https://docs.python.org/3/library/pickle.html

Les formats de protocole de pickle:

La version 0 du protocole est le protocole original "lisible par l'homme" et est rétrocompatible avec les versions antérieures de Python.

La version 1 du protocole est un ancien format binaire compatible avec les versions antérieures de Python.

La version 2 du protocole a été introduite dans Python 2.3. Il permet un décapage beaucoup plus efficace des classes d'un nouveau style. Reportez-vous au PEP 307 pour plus d'informations sur les améliorations apportées par le protocole 2.

La version 3 du protocole a été ajoutée dans Python 3.0. Il supporte explicitement les objets bytes et ne peut pas être annulé par Python 2.x. Il s'agit du protocole par défaut et du protocole recommandé lorsque la compatibilité avec d'autres versions de Python 3 est requise.

La version 4 du protocole a été ajoutée dans Python 3.4. Il ajoute la prise en charge des objets très volumineux, la sélection de plusieurs types d'objets et certaines optimisations de format de données. Reportez-vous au PEP 3154 pour plus d’informations sur les améliorations apportées par le protocole 4.

0
Gilco
import pickle

example_dict = {1:"6",2:"2",3:"g"}

pickle_out = open("dict.pickle","wb")
pickle.dump(example_dict, pickle_out)
pickle_out.close()

Le code ci-dessus sauvera le fichier pickle

pickle_in = open("dict.pickle","rb")
example_dict = pickle.load(pickle_in)

Ces deux lignes ouvriront le fichier pickle enregistré

0
Anirban Manna