やわらかテック

興味のあること。業務を通して得られた発見。個人的に試してみたことをアウトプットしています🍵

pandasでの保存形式はcsv、h5、pklでどれが良いのか

h5というファイル形式があることを知る

オライリーから発売されたpythonではじめるアルゴリズムトレードを読み進めていた所、金融の取引データをpandas.DataFrameからh5という形式のファイルに出力していました。h5というファイルは階層的データを扱うためのデータ形式であり、ディレクトリのように階層を経由して値へのアクセスが可能なようです。5というの現在の最新バージョンが5系であるためでそうで、過去にはh4が使用されていたのだそう。

ja.wikipedia.org

qiita.com

書籍では、h5のようなバイナリファイルとしてデータをダンプしておくことで、ハードウェアの性能を理論値の最大値まで引き出すことが可能と記載されています。読み込み時にも同様です。なので、インメモリで管理するよりもファイルに書き出しておいた方が良いということでしょうか。

なぜh5形式を採用したのか

ここについてあまり触れられていませんでした。書き込み速度や読み込み速度が他形式よりも高速なのか、メモリ効率が良いのか、アクセスが簡潔なためか分かりませんでした。 自分の知っている限りでは保存形式として.csv.pklも候補に上がります。また、今回は元データである金融の取引データが.csv形式のデータであったため、なおのこと.h5形式のメリットが分かりませんでした。

なので、.csv.h5.pklで読み込み時の速度をメインに比較をしてみました。書き込み時の速度はデータは読み込みケースの方がエンドユーザーは多いという仮説より測定していません。(面倒で(ry)

事前準備

データはpandas.DataFrameで適当なサイズのデータを作成します。numpyで作った適当なデータを格納しています。

def make_mock(rows_size, columns_size, file_name):
  df = pd.DataFrame(
    np.arange(rows_size * columns_size).reshape(rows_size, columns_size),
    columns=[f"col_{n}" for n in range(columns_size)],
    index=[f"idx_{n}" for n in range(rows_size)],
  )
  df.to_csv(f"{file_name}.csv")
  df.to_hdf(f"{file_name}.h5", key='df', mode='w')
  df.to_pickle(f"{file_name}.pkl")

以下は100行5列で作成したpandas.DataFrameinfo()の実行結果です。

<class 'pandas.core.frame.DataFrame'>
Index: 100 entries, idx_0 to idx_99
Data columns (total 5 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   col_0   100 non-null    int64
 1   col_1   100 non-null    int64
 2   col_2   100 non-null    int64
 3   col_3   100 non-null    int64
 4   col_4   100 non-null    int64
dtypes: int64(5)
memory usage: 4.7+ KB

このpandas.DataFrameをそれぞれのファイル形式に出力し、読み込み時の速度を計測します。

結果

rows size columns size extension user(ms) sys(ms) total(ms) wall time(ms) memory usage
100 5 csv 11.3 4 11.3 13.3 4.8KB
100 5 h5 13.5 0 13.5 13.8 4.7KB
100 5 pkl 11.2 3 11.2 15.7 4.7KB
10000 5 csv 23.1 911 24 31.5 468.9KB
10000 5 h5 21 870 21.9 23.1 468.8KB
10000 5 pkl 9.37 993 10.4 17 468.8KB
100000 5 csv 80.3 18.3 98.5 101 4.6MB
100000 5 h5 78.5 7.89 86.4 91 4.6MB
100000 5 pkl 27.4 5.11 32.5 54.6 4.6MB

金融の取引データのような時系列を主とするデータは行数は増えることはあっても、列数が増えることは行数が増える事に比べれば稀だという判断より、行数を100, 10000, 100000で結果を取っています。
行数は適当な数値です。全体的に各形式でそれほど、大きな差はないように見えます。面白いのは.pkl形式が行数が少ない時は遅かったのですが、行数が増えると他形式よりも倍近く速いです。

また、メモリ使用量(インメモリへpandas.DataFrameを展開した際の使用量)はほとんど差はありません。違いが出るのは速度だけだと考えて良さそうです。 汎用性も高い.pklを使うのが良いんじゃない?という結果になりました。

総括

おそらく、この程度のデータ量ではどれも対して変わらないのでしょう。また、今回は金融の取引という特定ドメインのデータで、pandasを使うことを前提としていました。
汎用性やユースケースによって適切なデータ形式が変わってくるとは思いますが、.pklを無難に選んでおけば良いのではないでしょうか。