Was sind die Unterschiede zwischen Feder und Parkett?


89

Beide sind Spalten- (Platten-) Speicherformate zur Verwendung in Datenanalysesystemen. Beide sind in Apache Arrow ( Pyarrow- Paket für Python) integriert und entsprechen Arrow als säulenförmige In-Memory-Analyseebene.

Wie unterscheiden sich beide Formate?

Sollten Sie bei der Arbeit mit Pandas nach Möglichkeit immer Federn bevorzugen?

Was sind die Anwendungsfälle, in denen Federn besser geeignet sind als Parkett und umgekehrt?


Blinddarm

Ich habe hier einige Hinweise gefunden: https://github.com/wesm/feather/issues/188 , aber angesichts des jungen Alters dieses Projekts ist es möglicherweise etwas veraltet.

Kein ernsthafter Geschwindigkeitstest, da ich nur einen ganzen Datenrahmen entleere und lade, aber um Ihnen einen Eindruck zu vermitteln, wenn Sie noch nie von den Formaten gehört haben:

 # 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

Antworten:


131
  • Das Parkettformat ist für die Langzeitspeicherung konzipiert, wobei Arrow eher für die Kurzzeit- oder kurzlebige Speicherung gedacht ist (Arrow eignet sich möglicherweise besser für die Langzeitspeicherung nach der Veröffentlichung von 1.0.0, da das Binärformat dann stabil ist.)

  • Das Schreiben von Parkett ist teurer als das von Feather, da es mehr Codierungs- und Komprimierungsschichten bietet. Feather ist ein unveränderter roher Säulenpfeilspeicher. Wir werden Feather wahrscheinlich in Zukunft eine einfache Komprimierung hinzufügen.

  • Aufgrund der Wörterbuchcodierung, RLE-Codierung und Datenseitenkomprimierung sind Parkettdateien häufig viel kleiner als Feather-Dateien

  • Parkett ist ein Standardspeicherformat für Analysen, das von vielen verschiedenen Systemen unterstützt wird: Spark, Hive, Impala, verschiedene AWS-Services, zukünftig von BigQuery usw. Wenn Sie also Analysen durchführen, ist Parkett eine gute Option als Referenzspeicherformat für Abfrage durch mehrere Systeme

Die von Ihnen angezeigten Benchmarks werden sehr verrauscht sein, da die von Ihnen gelesenen und geschriebenen Daten sehr klein sind. Sie sollten versuchen, mindestens 100 MB oder mehr 1 GB Daten zu komprimieren, um informativere Benchmarks zu erhalten. Siehe z. B. http://wesmckinney.com/blog/python-parquet-multithreading/

Hoffe das hilft


2
Ja, "unkomprimiert" wird immer eine Option sein
Wes McKinney

1
Ich habe festgestellt, dass Ihre generate_floatsFunktion in Ihrem Benchmark-Code hier wesmckinney.com/blog/python-parquet-update keine Garantie bietet unique_values. Sie sind nur zufällig. Mit n = 100M habe ich zwei von zehn Läufen doppelt erhalten. Nur erwähnen, falls jemand diese Funktion verwendet, bei der die Eindeutigkeit garantiert werden soll.
Darkonaut

1
@Darkonaut wundert sich nur ... Komprimierung führt zu einer kleineren Größe, sodass es schneller in den Speicher eingelesen werden kann. Es kann sein, dass die zusätzliche Verarbeitung aufgrund des Komprimierens / Dekomprimierens immer noch schneller ist, als wenn mehr Bytes gelesen werden müssen. Oder haben Sie eine Situation, an die ich nicht denke?
PascalVKooten

1
HDF5 ist allgemeiner und schwerer ... auch die meiste Zeit viel langsamer.
ivo Welch

3
@WesMcKinney Ich habe festgestellt, dass Ihre Antwort im Jahr 2018 geschrieben wurde. Denken Sie nach 2,3 Jahren immer noch, dass Pfeil (Feder) nicht für die Langzeitlagerung geeignet ist (im Vergleich zu Parkett)? Gibt es einen bestimmten Grund? Wie Stabilität? Formatentwicklung? oder?
HCSF
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.