Quais são as diferenças entre pena e parquet?

95

Ambos são formatos de armazenamento em colunas (disco) para uso em sistemas de análise de dados. Ambos estão integrados no Apache Arrow ( pacote pyarrow para python) e são projetados para corresponder a Arrow como uma camada analítica em memória colunar.

Como os dois formatos diferem?

Você sempre deve preferir penas ao trabalhar com pandas, quando possível?

Quais são os casos de uso em que a pena é mais adequada do que o parquet e vice- versa?


Apêndice

Encontrei algumas dicas aqui https://github.com/wesm/feather/issues/188 , mas dada a pouca idade deste projeto, é possivelmente um pouco desatualizado.

Não é um teste de velocidade sério porque estou apenas despejando e carregando um Dataframe inteiro, mas para lhe dar uma impressão, se você nunca ouviu falar dos 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
Darkonauta
fonte

Respostas:

136
  • O formato Parquet é projetado para armazenamento de longo prazo, onde o Arrow é mais destinado ao armazenamento de curto prazo ou efêmero (o Arrow pode ser mais adequado para o armazenamento de longo prazo após o lançamento 1.0.0, já que o formato binário será estável então)

  • Parquet é mais caro de escrever do que Feather, pois apresenta mais camadas de codificação e compactação. Pena é a memória colunar crua e não modificada de Arrow. Provavelmente adicionaremos compactação simples ao Feather no futuro.

  • Devido à codificação de dicionário, codificação RLE e compactação de página de dados, os arquivos Parquet costumam ser muito menores do que os arquivos Feather

  • Parquet é um formato de armazenamento padrão para análise que é compatível com muitos sistemas diferentes: Spark, Hive, Impala, vários serviços AWS, no futuro por BigQuery, etc. Portanto, se você estiver fazendo análises, Parquet é uma boa opção como formato de armazenamento de referência consulta por vários sistemas

Os benchmarks que você mostrou serão muito barulhentos, pois os dados que você lê e escreve são muito pequenos. Você deve tentar compactar pelo menos 100 MB ou mais de 1 GB de dados para obter alguns benchmarks mais informativos, consulte, por exemplo, http://wesmckinney.com/blog/python-parquet-multithreading/

Espero que isto ajude

Wes McKinney
fonte
3
Sim, "descompactado" sempre será uma opção
Wes McKinney
1
Percebi que sua generate_floatsfunção em seu código de benchmark aqui wesmckinney.com/blog/python-parquet-update não garante unique_values. Eles são apenas aleatórios. Com n = 100M, obtive duplicatas em duas de dez execuções. Apenas mencionando caso alguém use esta função onde a exclusividade deve ser garantida.
Darkonaut
1
@Darkonaut apenas pensando ... a compressão resulta em um tamanho menor, então seria mais rápido lê-lo na memória. Pode ser que o processamento extra devido à compactação / descompactação seja ainda mais rápido do que ter que ler mais bytes. Ou você tem uma situação na qual não estou pensando?
PascalVKooten
2
HDF5 é mais geral e pesado ... também muito mais lento na maioria das vezes.
ivo Welch
4
@WesMcKinney Percebi que sua resposta foi escrita em 2018. Depois de 2,3 anos, você ainda acha que Arrow (pena) não é bom para armazenamento de longo prazo (em comparação com Parquet)? Existe um motivo específico? Gosta de estabilidade? evolução do formato? ou?
HCSF