pandas.DataFrame, Seriesをpickleで保存、読み込み(to_pickle, read_pickle)
pandas.DataFrame
, pandas.Series
オブジェクトをそのままpickleファイルとして保存するにはto_pickle()
メソッド、保存したpickleファイルを読み込むにはpd.read_pickle()
関数を使う。
- pandas.DataFrame.to_pickle — pandas 0.23.4 documentation
- pandas.read_pickle — pandas 0.23.4 documentation
ここでは以下の内容について説明する。
- pickleとは
- pandasでpickleを使う利点
- CSVファイルで保存・読み込みする場合
- pickleファイルで保存・読み込みする場合
- 圧縮処理
pickleとは
pickleはPython標準ライブラリに含まれているモジュールで、Pythonオブジェクトをバイト列に変換(シリアライズ、pickle化)したり、バイト列からPythonオブジェクトに変換(デシリアライズ、非pickle化)したりするために使われる。
便宜上、ここではpickle化されて保存されたファイルをpickleファイルと呼ぶこととする。
なお、上記pickleモジュールのドキュメントにあるように出所不明なpickleファイルは危険な可能性があるので注意。
警告 pickle モジュールはエラーや不正に生成されたデータに対して安全ではありません。信頼できない、あるいは認証されていないソースから受け取ったデータを非 pickle 化してはいけません。
12.1. pickle --- Python オブジェクトの直列化 — Python 3.6.6 ドキュメント
pandasでpickleを使う利点
pandasではpandas.DataFrame
, pandas.Series
オブジェクトをCSVファイルやJSONファイルなどの形式で保存したり読み込んだりするメソッドが用意されている。
- 関連記事: pandasでcsv/tsvファイル読み込み(read_csv, read_table)
- 関連記事: pandasでJSON文字列・ファイルを読み込み(read_json)
- 関連記事: pandasでExcelファイル(xlsx, xls)の読み込み(read_excel)
pickleファイルはCSVファイルやJSONファイルなどと異なりエディタで中身を確認したり他のアプリケーションで使い回すことはできないが、保存時・読み込み時に特別な設定や処理をすることなくオブジェクトをそのまま読み書きできるという利点がある。
以下のpandas.DataFrame
を例とする。日時情報をインデックスとする時系列データで、'list'
列にはlist
型オブジェクトが格納されている。
import pandas as pd
df = pd.DataFrame({'list': [[0, 0], [0, 1], [1, 0], [1, 1]]},
index=pd.date_range('2018-01-01', '2018-01-04', freq='D'))
print(df)
# list
# 2018-01-01 [0, 0]
# 2018-01-02 [0, 1]
# 2018-01-03 [1, 0]
# 2018-01-04 [1, 1]
print(df.index)
# DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04'], dtype='datetime64[ns]', freq='D')
print(type(df['list'][0]))
# <class 'list'>
CSVファイルで保存・読み込みする場合
CSVで保存して再度読み込む場合、まず、時系列データとしてインデックスを指定するためにread_csv()
の引数index_col
やparse_dates
を指定する必要がある。
df.to_csv('data/dst/pandas_obj.csv')
df_from_csv = pd.read_csv('data/dst/pandas_obj.csv', index_col=0, parse_dates=True)
print(df_from_csv)
# list
# 2018-01-01 [0, 0]
# 2018-01-02 [0, 1]
# 2018-01-03 [1, 0]
# 2018-01-04 [1, 1]
print(df_from_csv.index)
# DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04'], dtype='datetime64[ns]', freq=None)
さらに、'list'
列は文字列として読み込まれるので、例えば組み込み関数eval()
を各要素に適用してlist
型オブジェクトに変換する必要がある。
print(type(df_from_csv['list'][0]))
# <class 'str'>
df_from_csv['list'] = df_from_csv['list'].apply(eval)
print(df_from_csv)
# list
# 2018-01-01 [0, 0]
# 2018-01-02 [0, 1]
# 2018-01-03 [1, 0]
# 2018-01-04 [1, 1]
print(type(df_from_csv['list'][0]))
# <class 'list'>
pickleファイルで保存・読み込みする場合
to_pickle()
, read_pickle()
を使ってpickleファイルとして扱う場合、引数の指定や変換処理をする必要なくオブジェクトを保存でき、そのままの状態で復元できる。
df.to_pickle('data/dst/pandas_obj.pkl')
df_from_pkl = pd.read_pickle('data/dst/pandas_obj.pkl')
print(df_from_pkl)
# list
# 2018-01-01 [0, 0]
# 2018-01-02 [0, 1]
# 2018-01-03 [1, 0]
# 2018-01-04 [1, 1]
print(df_from_pkl.index)
# DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04'], dtype='datetime64[ns]', freq='D')
print(type(df_from_pkl['list'][0]))
# <class 'list'>
作業を一時中断するためにオブジェクトの状態を保存しておきたい場合などにも、特に何も考える必要がないpickleファイルは便利。
さらに、CSVなどに比べて処理速度が速いというメリットもある。
圧縮処理
拡張子を.gz
, .bz2
, .xz
, .zip
として指定すると、自動で圧縮・解凍処理が行われる。
df.to_pickle('data/dst/pandas_obj.zip')
df_from_pkl_zip = pd.read_pickle('data/dst/pandas_obj.zip')
print(df_from_pkl_zip)
# list
# 2018-01-01 [0, 0]
# 2018-01-02 [0, 1]
# 2018-01-03 [1, 0]
# 2018-01-04 [1, 1]
引数compression
に明示的に形式('gzip'
, 'bz2'
, 'xz'
, 'zip'
)を指定することも可能。