¿Cuáles son las diferencias entre la pluma y el parquet?

89

Ambos son formatos de almacenamiento en columna (disco) para su uso en sistemas de análisis de datos. Ambos están integrados dentro de Apache Arrow ( paquete pyarrow para python) y están diseñados para corresponder con Arrow como una capa analítica en memoria en columnas.

¿En qué se diferencian ambos formatos?

¿Debería preferir siempre las plumas cuando trabaja con pandas cuando sea posible?

¿Cuáles son los casos de uso en los que la pluma es más adecuada que el parquet y al revés?


Apéndice

Encontré algunas pistas aquí https://github.com/wesm/feather/issues/188 , pero 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 Dataframe completo, pero para darte una impresión si nunca has oído hablar de los formatos antes:

 # 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
Darkonaut
fuente

Respuestas:

131
  • El formato Parquet está diseñado para almacenamiento a largo plazo, donde Arrow está más diseñado para almacenamiento a corto plazo o efímero (Arrow puede ser más adecuado para almacenamiento a largo plazo después de que se produzca la versión 1.0.0, ya que el formato binario será estable en ese momento)

  • Parquet es más caro de escribir que Feather, ya que presenta más capas de codificación y compresión. Feather es una memoria de flecha columnar sin modificar 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 a menudo serán 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 por BigQuery, etc. Por lo tanto, si está haciendo análisis, Parquet es una buena opción como formato de almacenamiento de referencia para consulta por múltiples sistemas

Los puntos de referencia que mostró serán muy ruidosos ya que los datos que leyó y escribió son muy pequeños. Debería 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

Wes McKinney
fuente
2
Sí, "sin comprimir" siempre será una opción
Wes McKinney
1
Me di cuenta de que su generate_floatsfunción en su código de referencia aquí wesmckinney.com/blog/python-parquet-update no garantiza unique_values. Son simplemente aleatorios. Con n = 100M obtuve duplicados dos de cada diez ejecuciones. Solo menciono en caso de que alguien use esta función donde se debe garantizar la singularidad.
Darkonaut
1
@Darkonaut solo se pregunta ... la compresión da como resultado un tamaño más pequeño, por lo que sería más rápido leerlo en la memoria. Podría ser que el procesamiento adicional debido a la compresión / descompresión sea aún más rápido que tener que leer más bytes. ¿O tienes una situación en la que no estoy pensando?
PascalVKooten
1
HDF5 es más general y pesado ... también mucho más lento la mayor parte del tiempo.
ivo Welch
3
@WesMcKinney Noté que su respuesta fue escrita en 2018. Después de 2.3 años, ¿todavía cree 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