盆暗の学習記録

データサイエンス ,エンジニアリング,ビジネスについて日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

CSVとFeather, Parquetを比較してみる

最近Parquetというファイルフォーマットを知りました。S3にデータを置いてDWHを作ったりする際などに使うようです。

pyarrowパッケージをインストールしていればpandasからFeatherやParquetにお手軽に保存できることに気づいたので試してみてCSVと比較してみます。

比較方法

以下のようなランダムな値を入れたレコードを生成させてテストデータに使用します。

import random
from time import time
from string import ascii_letters
import pandas as pd
from pathlib import Path


def random_datetime():
    return pd.Timestamp(
        year=int(random.uniform(1990, 2020)),
        month=int(random.uniform(1, 12)),
        day=int(random.uniform(1, 28)),
        hour=int(random.uniform(1, 23)),
        minute=int(random.uniform(1, 59)),
    )

def gen_data(n=100):
    return pd.DataFrame({
        "int": list(range(n)),
        "float": [random.random() for _ in range(n)],
        "bool": [random.choice([True, False]) for _ in range(n)],
        "string": [''.join(random.choices(ascii_letters, k=10)) for _ in range(n)],
        "date": [random_datetime().date() for _ in range(n)],
        "datetime": [random_datetime() for _ in range(n)]
    })

そして、

  1. ファイルの保存(ディスクの書き込み)にかかった時間
  2. ファイルの読み込みにかかった時間
  3. ファイルサイズ

を比較してみます。

保存と読み込みは10回繰り返して平均をとります。

レコード数は [10_000, 100_000, 1_000_000, 10_000_000, 20_000_000] で試します。

保存時のオプション引数はデフォルトから変更せず(圧縮アルゴリズムなどは変えず)以下のように保存します。

df.to_csv('df.csv', index=False)
df.to_feather('df.feather')
df.to_parquet('df.parquet', index=False)

なお検証時のバージョンは以下の通りです。

  • python == 3.8
  • pyarrow == 7.0.0
  • pandas == 1.2.0

結果

保存速度

ファイルの保存にかかった時間は実数では上のグラフのようになりました。

f:id:nigimitama:20220305223754p:plain

CSVに比べた変化率は以下の表のようになります。

n feather parquet
10,000 -78.4% -69.6%
100,000 -95.0% -90.1%
1,000,000 -95.9% -93.9%
10,000,000 -96.0% -94.8%
20,000,000 -96.0% -94.8%

featherで78%~96%削減、parquetで70%~95%削減されました。レコード数が10,000のときが最も削減効率が悪かったです。

featherもparquetもcsvに比べると段違いに速いですが、featherのほうがparquetよりも若干速いですね。

読み込み速度

読み込みにかかった時間は次のグラフのようになります。

f:id:nigimitama:20220305223809p:plain

CSVに比べた変化率は以下の表のようになります。featherもparquetもcsvに比べると段違いに速いです。featherのほうがparquetより速いですね。

n feather parquet
10,000 -48.9% -22.0%
100,000 -73.0% -66.9%
1,000,000 -73.4% -71.3%
10,000,000 -70.0% -65.1%
20,000,000 -68.1% -53.4%

ファイルサイズ

ファイルサイズはCSVの半分程度になりました。

f:id:nigimitama:20220305222415p:plain

parquetはレコード数が増えるほどファイルサイズの削減効率が高まるようです。

n feather parquet
10,000 -47.2% -39.1%
100,000 -48.0% -41.9%
1,000,000 -48.7% -52.7%
10,000,000 -49.4% -54.6%
20,000,000 -49.8% -55.0%

(参考)グラフの元データ

上記のグラフの元となった具体的な数値の表も載せておきます。

n format write_mean write_std read_mean read_std size
10000 csv 0.044 0.001 0.013 0.001 0.683
10000 feather 0.010 0.009 0.007 0.000 0.360
10000 parquet 0.014 0.009 0.010 0.008 0.416
100000 csv 0.425 0.005 0.101 0.003 6.929
100000 feather 0.021 0.001 0.027 0.001 3.606
100000 parquet 0.042 0.002 0.033 0.004 4.024
1000000 csv 4.268 0.030 1.060 0.018 70.248
1000000 feather 0.175 0.007 0.282 0.004 36.026
1000000 parquet 0.261 0.008 0.304 0.006 33.239
10000000 csv 43.220 0.294 11.146 0.245 711.997
10000000 feather 1.709 0.023 3.346 0.108 360.235
10000000 parquet 2.257 0.050 3.895 0.106 323.421
20000000 csv 86.777 0.370 26.038 1.720 1434.600
20000000 feather 3.458 0.054 8.299 0.439 720.470
20000000 parquet 4.518 0.137 12.126 0.866 645.739

まとめ

データ分析時に前処理済みの訓練データの保存を行う際はcsvよりもfeatherやparquetのほうが良さそうですね。

「レコード数が極端に多いデータで、書き込み・読み込みの速度よりもファイルサイズの圧縮を重視したい」という場合はparquetのほうが良さそうですが、そうでない場合はfeatherが扱いやすそうです。