pandas
Python Data Analysis Library — pandas: Python Data Analysis Library
2次元データの集計分析に特化したパッケージ。
- チートシート
- 詳しくまとまった解説
使用シーン
2次元データの解析なら大抵は何にでも使えるが(3次元以上でも正規化すればおk)一部、向かないシーンもある。
使用に向かないシーン
巨大データ
データを一度にメモリ上に読み込むため、巨大なデータを扱うにはそれなりのメモリが必要になる。 中身のデータ型に大きく依るが、CSVで500MBなら読み込んだときには1GBくらいにはなることもある。
小数型や長整数型、NaNを含むデータは、デフォルトでは64bit型に変換されるためより増える。そこまでの精度が要らない場合は、32bit型などを指定してから読めばよい。そもそも各列にどの程度の精度が必要なのか不明な場合、一部だけ試験的に読み込み、df.describe()などで基礎集計値を見れる。
巨大なデータから一定条件で抽出したデータのみがあれば良い場合は分割して読み込むこともできるが、pandasを使わず逐次処理も考慮に入れた方がよい。
イテレートが必要
時系列データで前後の内容によって処理が変わるとか場合分けがあるとかで、行方向のイテレートが必要な場合は、pandasを利用しない選択肢を考えるべき。もしくはイテレートが必要なタイミングでリストに変換する。
- イテレートがとても遅い
- 勝手に型が変わる
遅い理由ははおそらくpandasがDataFrameを保持するのに用いているNumPyのイテレートがそもそも遅いため。まとめて同じ計算をすることに特化している代わりにランダムアクセスやイテレートの速度は犠牲となっている。
イテレートで書きたくなるような処理でも、カラムを追加したり上手くやればpandasでできるんだろうけど、パッと思いつかない場合は方法を考えるのに時間をかけるより、さっさとforで回して順番に処理した方が速い。
また、pandasを行方向にイテレートする iterrows()
では特に勝手に型変換が行われるらしく、[int, float, float] という型を持つ3カラムを回すと、[float, float, float] に変わってしまったりする。これも何気に煩わしいし、速度を落としている原因になってやしないか気になる。
Tips
巨大csvファイルの読み込み
pandas でメモリに乗らない 大容量ファイルを上手に扱う - StatsFragments
- pd.read_csv()の引数に
chunksize=50
などとして一度に読み込む行数を渡す - pd.read_csv()の結果はDataFrameでなくTextFileReaderで返ってくる。ループで回すとchunksizeごとのDataFrameを取り出せる
- 「一度に読み込むと巨大でも、そこから抽出したデータはメモリに乗る」のでまとめて扱いたい場合、pd.concat()で結合できる
- その際、既についてしまったindexは無視させるため、引数に
ignore_index=True
を指定する
パフォーマンス維持
Python pandas パフォーマンス維持のための 3 つの TIPS - StatsFragments
- 本当に速さを求めるならCythonやNumbaといったCコーディングを検討した方がよい
- 手軽なPython/pandasを使いつつ、速度を遅くする書き方を避ける折衷策
- DataFrame.applyは避ける
- 連続してpython関数を呼び出すため。特にrowに対する処理は、より遅い
- 代わりに1columnをそのままnumpy.arrayとして取ってきて、ベクトル演算を使う
- 関数はnumpy.vectorize()でベクトル化できる……が、これも実は内部ではイテレートしてるので、速くはならない
- rowごとにイテレートしなければならない処理は、結局pandasには向かない
- Object型は避ける
- NaNが混じった文字列データなどは、自動的にはObject型として解釈される。これの処理は結構遅い
- astype('category')でカテゴリー化すると、マスタデータを別に作成し、内部はint型での処理になるため速い
- indexはユニーク化・ソートする
- そうでないデータと内部処理が異なり、速くなる