Cómo almacenar un dataframe utilizando Pandas

En este momento, estoy importando un archivo CSV bastante grande como dataframe cada vez que ejecuto el script. ¿Existe una buena solución para mantener ese dataframe constantemente disponible entre las ejecuciones para que no tenga que pasar todo ese tiempo esperando a que se ejecute el script?

La forma más fácil es to_pickle con to_pickle :

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

Luego puedes volver a cargarlo usando:

 df = pd.read_pickle(file_name) 

Nota: antes de 0.11.1, save y load eran la única forma de hacer esto (ahora están en desuso en favor de to_pickle y read_pickle respectivamente).


Otra opción popular es usar HDF5 ( pytables ), que ofrece tiempos de acceso muy rápidos para grandes conjuntos de datos:

 store = HDFStore('store.h5') store['df'] = df # save it store['df'] # load it 

Las estrategias más avanzadas se discuten en el libro de cocina .


Desde 0.13 también hay un msgpack que puede ser mejor para la interoperabilidad, como una alternativa más rápida a JSON, o si tiene datos de texto / objeto de Python (consulte esta pregunta ).

Aunque ya hay algunas respuestas, encontré una buena comparación en la que intentaron varias formas de serializar Pandas DataFrames: Almacenar eficientemente Pandas DataFrames .

Ellos comparan:

  • pickle: formato de datos ASCII original
  • cPickle, una biblioteca de C
  • pickle-p2: usa el formato binario más nuevo
  • json: standardlib json library
  • json-no-index: como json, pero sin índice
  • msgpack: alternativa JSON binaria
  • CSV
  • hdfstore: formato de almacenamiento HDF5

En su experimento, serializan un DataFrame de 1,000,000 de filas con las dos columnas probadas por separado: una con datos de texto, la otra con números. Su renuncia dice:

No debes confiar en que lo que sigue generaliza a tus datos. Debes mirar tus propios datos y ejecutar los puntos de referencia por ti mismo.

El código fuente de la prueba a la que hacen referencia está disponible en línea . Como este código no funcionaba directamente, hice algunos cambios menores, que puede obtener aquí: serialize.py Obtuve los siguientes resultados:

resultados de comparación de tiempo

También mencionan que con la conversión de datos de texto a datos categóricos , la serialización es mucho más rápida. En su prueba, aproximadamente 10 veces más rápido (vea también el código de prueba).

Edición : los tiempos más altos para pickle que csv pueden explicarse por el formato de datos utilizado. Por defecto, pickle utiliza una representación ASCII imprimible, que genera conjuntos de datos más grandes. Sin embargo, como puede verse en el gráfico, el pickle con el formato de datos binarios más nuevos (versión 2, pickle-p2 ) tiene tiempos de carga mucho más bajos.

Algunas otras referencias:

  • En la pregunta sobre la biblioteca de Python más rápida para leer un archivo CSV hay una respuesta muy detallada que compara diferentes bibliotecas para leer archivos csv con un punto de referencia. El resultado es que para leer archivos csv, numpy.fromfile es el más rápido.
  • Otra prueba de serialización muestra que msgpack-python , ujson y cPickle son los más rápidos en serializar.

Si entiendo correctamente, ya estás usando pandas.read_csv() pero te gustaría acelerar el proceso de desarrollo para que no tengas que cargar el archivo cada vez que edites tu script, ¿no es así? Tengo algunas recomendaciones:

  1. puede cargar solo una parte del archivo CSV utilizando pandas.read_csv(..., nrows=1000) para cargar solo el bit superior de la tabla, mientras realiza el desarrollo

  2. use ipython para una sesión interactiva, de modo que mantenga la tabla de pandas en la memoria mientras edita y vuelve a cargar su script.

  3. convertir el csv a una tabla HDF5

  4. uso actualizado DataFrame.to_feather() y pd.read_feather() para almacenar datos en formato binario pluma compatible con R que es súper rápido (en mis manos, ligeramente más rápido que pandas.to_pickle() en datos numéricos y mucho más rápido en datos de cadenas ).

También podría estar interesado en esta respuesta en stackoverflow.

¡El pepinillo funciona 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 

Los Pandas DataFrames tienen la función to_pickle que es útil para guardar un DataFrame:

 import pandas as pd a = pd.DataFrame({'A':[0,1,0,1,0],'B':[True, True, False, False, False]}) print a # AB # 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 # AB # 0 0 True # 1 1 True # 2 0 False # 3 1 False # 4 0 False 

Puede utilizar el archivo de formato de pluma. Es extremadamente rápido.

 df.to_feather('filename.ft') 

Los formatos de archivo desiguales son bastante rápidos para datos numéricos

Prefiero usar archivos numpy ya que son rápidos y fáciles de usar. Aquí hay un punto de referencia simple para guardar y cargar un dataframe con 1 columna de 1 millón de puntos.

 import numpy as np import pandas as pd num_dict = {'voltage': np.random.rand(1000000)} num_df = pd.DataFrame(num_dict) 

usando la función mágica %%timeit

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

la salida es

 100 loops, best of 3: 5.97 ms per loop 

para cargar los datos de nuevo en un dataframe

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

la salida es

 100 loops, best of 3: 5.12 ms per loop 

¡NO ESTÁ MAL!

CONTRAS

Existe un problema si guarda el archivo numpy con python 2 y luego intenta abrirlo con python 3 (o viceversa).

Como ya se mencionó, existen diferentes opciones y formatos de archivo ( HDF5 , JSON , CSV , parquet , SQL ) para almacenar un dataframe. Sin embargo, el que no debería estar en la lista es pickle .

1) La pickle es un riesgo potencial para la seguridad. Forma la documentación de Python para pickle :

Advertencia El módulo pickle no es seguro contra datos erróneos o construidos malintencionadamente. Nunca descomprima los datos recibidos de una fuente no confiable o no autenticada.

2) El pickle es lento. Encuentra aquí y aquí puntos de referencia.

Dependiendo de su configuración / uso, ambas limitaciones no se aplican, pero no recomendaría pickle como la persistencia predeterminada para los marcos de datos pandas.

 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() 

El código anterior guardará el archivo pickle

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

Estas dos líneas abrirán el archivo de salmuera guardado

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

Los formatos del protocolo pickle:

La versión 0 del protocolo es el protocolo original “legible por humanos” y es compatible con versiones anteriores de Python.

La versión 1 del protocolo es un formato binario antiguo que también es compatible con versiones anteriores de Python.

La versión 2 del protocolo se introdujo en Python 2.3. Proporciona un decapado mucho más eficiente de las clases de nuevo estilo. Consulte la PEP 307 para obtener información sobre las mejoras traídas por el protocolo 2.

Protocolo versión 3 fue añadido en Python 3.0. Tiene soporte explícito para objetos de bytes y no puede ser eliminado por Python 2.x. Este es el protocolo predeterminado, y el protocolo recomendado cuando se requiere compatibilidad con otras versiones de Python 3.

Protocolo versión 4 fue añadido en Python 3.4. Agrega soporte para objetos muy grandes, escogiendo más tipos de objetos y algunas optimizaciones de formato de datos. Consulte la PEP 3154 para obtener información sobre las mejoras traídas por el protocolo 4.