Ambos son formatos de almacenamiento en columnas (disco) para su uso en sistemas de análisis de datos. Ambos están integrados dentro flecha apache (flecha paquete para python) y están diseñados para corresponder con Flecha como una capa de análisis columnar en memoria.
¿En qué se diferencian ambos formatos?
¿Deberías preferir siempre las plumas cuando trabajes con pandas cuando sea posible?
¿Cuáles son los casos de uso donde pluma es más adecuado que parquet y al revés?
Apéndice
Encontré algunos consejos aquí. https://github.com/wesm/feather/issues/188pero dada la corta edad de este proyecto, posiblemente esté un poco desactualizado.
No es una prueba de velocidad seria porque solo estoy descargando y cargando un marco de datos completo, pero para darle una impresión si nunca antes había oído hablar de los formatos:
# IPython
import numpy as np
import pandas as pd
import pyarrow as pa
import pyarrow.feather as feather
import pyarrow.parquet as pq
import fastparquet as fp
df = pd.DataFrame({'one': [-1, np.nan, 2.5],
'two': ['foo', 'bar', 'baz'],
'three': [True, False, True]})
print("pandas df to disk ####################################################")
print('example_feather:')
%timeit feather.write_feather(df, 'example_feather')
# 2.62 ms ± 35.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
print('example_parquet:')
%timeit pq.write_table(pa.Table.from_pandas(df), 'example.parquet')
# 3.19 ms ± 51 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
print()
print("for comparison:")
print('example_pickle:')
%timeit df.to_pickle('example_pickle')
# 2.75 ms ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
print('example_fp_parquet:')
%timeit fp.write('example_fp_parquet', df)
# 7.06 ms ± 205 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
print('example_hdf:')
%timeit df.to_hdf('example_hdf', 'key_to_store', mode="w", table=True)
# 24.6 ms ± 4.45 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
print()
print("pandas df from disk ##################################################")
print('example_feather:')
%timeit feather.read_feather('example_feather')
# 969 µs ± 1.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
print('example_parquet:')
%timeit pq.read_table('example.parquet').to_pandas()
# 1.9 ms ± 5.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
print("for comparison:")
print('example_pickle:')
%timeit pd.read_pickle('example_pickle')
# 1.07 ms ± 6.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
print('example_fp_parquet:')
%timeit fp.ParquetFile('example_fp_parquet').to_pandas()
# 4.53 ms ± 260 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
print('example_hdf:')
%timeit pd.read_hdf('example_hdf')
# 10 ms ± 43.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# pandas version: 0.22.0
# fastparquet version: 0.1.3
# numpy version: 1.13.3
# pandas version: 0.22.0
# pyarrow version: 0.8.0
# sys.version: 3.6.3
# example Dataframe taken from https://arrow.apache.org/docs/python/parquet.html
-
El formato parquet está diseñado para el almacenamiento a largo plazo, donde Arrow está más destinado al almacenamiento a corto plazo o efímero (Arrow puede ser más adecuado para el almacenamiento a largo plazo después de la versión 1.0.0, ya que el formato binario será estable entonces)
-
Parquet es más costoso de escribir que Feather, ya que presenta más capas de codificación y compresión. Feather es una memoria Arrow columnar sin modificar. Probablemente agregaremos compresión simple a Feather en el futuro.
-
Debido a la codificación del diccionario, la codificación RLE y la compresión de la página de datos, los archivos Parquet suelen ser mucho más pequeños que los archivos Feather.
-
Parquet es un formato de almacenamiento estándar para análisis que es compatible con muchos sistemas diferentes: Spark, Hive, Impala, varios servicios de AWS, en el futuro BigQuery, etc. Por lo tanto, si realiza análisis, Parquet es una buena opción como formato de almacenamiento de referencia para consulta por varios sistemas
Los puntos de referencia que mostraste serán muy ruidosos ya que los datos que lees y escribes son muy pequeños. Debe intentar comprimir al menos 100 MB o más de 1 GB de datos para obtener algunos puntos de referencia más informativos, consulte, por ejemplo http://wesmckinney.com/blog/python-parquet-multithreading/
Espero que esto ayude
-
Sí, “sin comprimir” siempre será una opción
–Wes McKinney
06/01/2018 a las 19:15
-
HDF5 es más general y pesado… también mucho más lento la mayor parte del tiempo.
– ivo Welch
27 de agosto de 2019 a las 20:57
-
Sólo para añadir una observación, 200.000 imágenes en formato parquet ocupaban 4 GB, pero en pluma ocupaban 6 GB. Los datos se leyeron usando pandas pd.read_parquet y pd.read_feather. pd.read_parquet tomó alrededor de 4 minutos, pero pd.read_feather tomó 11 segundos. Es una diferencia enorme. Referencia: kaggle.com/corochann/…
– Krisho
23 de enero de 2020 a las 11:23
-
@WesMcKinney Noté que su respuesta se escribió en 2018. Después de 2,3 años, ¿sigue pensando que Arrow (pluma) no es buena para el almacenamiento a largo plazo (en comparación con Parquet)? Hay una razón específica? ¿Te gusta la estabilidad? evolución del formato? ¿o?
– HCSF
23 de abril de 2020 a las 9:42
-
W. McKinney indica que la pluma (v2) ahora es estable aquí: stackoverflow.com/questions/64089691/…
– anon01
7 sep 2021 a las 17:59
artur dutra
También incluiría en la comparación entre el parquet y la pluma diferentes métodos de compresión para comprobar las velocidades de importación/exportación y la cantidad de almacenamiento que utiliza.
Abogo por 2 opciones para el usuario promedio que quiere una mejor alternativa csv:
- parquet con compresión “gzip” (para almacenamiento): es un poco más rápido de exportar que solo .csv (si es necesario comprimir el csv, entonces parquet es mucho más rápido). La importación es aproximadamente 2 veces más rápida que csv. La compresión es de alrededor del 22% del tamaño del archivo original, que es casi lo mismo que los archivos csv comprimidos.
- pluma con compresión “zstd” (para velocidad de E/S): en comparación con csv, la exportación de plumas tiene una exportación 20 veces más rápida y una importación aproximadamente 6 veces más rápida. El almacenamiento es alrededor de un 32% del tamaño del archivo original, que es un 10% peor que el parquet “gzip” y csv comprimido, pero sigue siendo decente.
Ambas son mejores opciones que los archivos csv normales en todas las categorías (velocidad de E/S y almacenamiento).
Analicé los siguientes formatos:
- CSV
- csv usando compresión “zip”
- pluma usando compresión “zstd”
- pluma usando compresión “lz4”
- parquet usando compresión “rápida”
- parquet con compresión “gzip”
- parquet usando “gzip” brotli
import zipfile
import pandas as pd
folder_path = (r"...\\intraday")
zip_path = zipfile.ZipFile(folder_path + "\\AAPL.zip")
test_data = pd.read_csv(zip_path.open('AAPL.csv'))
# EXPORT, STORAGE AND IMPORT TESTS
# ------------------------------------------
# - FORMAT .csv
# export
%%timeit
test_data.to_csv(folder_path + "\\AAPL.csv", index=False)
# 12.8 s ± 399 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# storage
# AAPL.csv exported using python.
# 169.034 KB
# import
%%timeit
test_data = pd.read_csv(folder_path + "\\AAPL.csv")
# 1.56 s ± 14.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# ------------------------------------------
# - FORMAT zipped .csv
# export
%%timeit
test_data.to_csv(folder_path + "\\AAPL.csv")
# 12.8 s ± 399 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# OBSERVATION: this does not include the time I spent manually zipping the .csv
# storage
# AAPL.csv zipped with .zip "normal" compression using 7-zip software.
# 36.782 KB
# import
zip_path = zipfile.ZipFile(folder_path + "\AAPL.zip")
%%timeit
test_data = pd.read_csv(zip_path.open('AAPL.csv'))
# 2.31 s ± 43.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# ------------------------------------------
# - FORMAT .feather using "zstd" compression.
# export
%%timeit
test_data.to_feather(folder_path + "\\AAPL.feather", compression='zstd')
# 460 ms ± 13.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# storage
# AAPL.feather exported with python using zstd
# 54.924 KB
# import
%%timeit
test_data = pd.read_feather(folder_path + "\\AAPL.feather")
# 310 ms ± 11.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# ------------------------------------------
# - FORMAT .feather using "lz4" compression.
# Only works installing with pip, not with conda. Bad sign.
# export
%%timeit
test_data.to_feather(folder_path + "\\AAPL.feather", compression='lz4')
# 392 ms ± 14.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# storage
# AAPL.feather exported with python using "lz4"
# 79.668 KB
# import
%%timeit
test_data = pd.read_feather(folder_path + "\\AAPL.feather")
# 255 ms ± 4.79 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# ------------------------------------------
# - FORMAT .parquet using compression "snappy"
# export
%%timeit
test_data.to_parquet(folder_path + "\\AAPL.parquet", compression='snappy')
# 2.82 s ± 47.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# storage
# AAPL.parquet exported with python using "snappy"
# 62.383 KB
# import
%%timeit
test_data = pd.read_parquet(folder_path + "\\AAPL.parquet")
# 701 ms ± 19.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# ------------------------------------------
# - FORMAT .parquet using compression "gzip"
# export
%%timeit
test_data.to_parquet(folder_path + "\\AAPL.parquet", compression='gzip')
# 10.8 s ± 77.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# storage
# AAPL.parquet exported with python using "gzip"
# 37.595 KB
# import
%%timeit
test_data = pd.read_parquet(folder_path + "\\AAPL.parquet")
# 1.18 s ± 80.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# ------------------------------------------
# - FORMAT .parquet using compression "brotli"
# export
%%timeit
test_data.to_parquet(folder_path + "\\AAPL.parquet", compression='brotli')
# around 5min each loop. I did not run %%timeit on this one.
# storage
# AAPL.parquet exported with python using "brotli"
# 29.425 KB
# import
%%timeit
test_data = pd.read_parquet(folder_path + "\\AAPL.parquet")
# 1.04 s ± 72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Observaciones:
- Feather parece mejor para datos livianos, ya que escribe y carga más rápido. El parquet tiene mejores proporciones de almacenamiento.
- El soporte y mantenimiento de la biblioteca Feather me preocupó inicialmente, sin embargo, el formato de archivo tiene una buena integración con pandas y pude instalar las dependencias usando
conda
para el método de compresión “zstd”. - El mejor almacenamiento, con diferencia, es el parquet con compresión “brotli”, sin embargo, lleva mucho tiempo exportarlo. Tiene una buena velocidad de importación una vez que se realiza la exportación, pero aún así es 2,5 veces más lenta que la pluma.