うめこの開発日記

PCゲームや人工知能関連の話題についての日記

Pandasのappendが遅すぎる時の対処法

Pandasのappendは遅い、遅すぎる...........
 

とある処理を行っていて、処理後の行をpandasのDataFrameに対してappendしていく場面が結構あると思います。
行数が数万ぐらいのデータであれば、appendを使っても特に困ることはないと思うのですが(それならappend便利)、数千万行のデータになるとappendの遅さが顕著になります。

appendは非破壊的な動作をするので、元のDataFrameを変化させません。つまり...

df = pd.DataFrame()
df = df.append(row)

のようにいちいち元のDataFrameに代入する必要があるわけです。
このとき、appendによって元のDataFrameのコピーが作成されるわけで、元のDataFrameのサイズが大きくなるほどコピーに時間がかかり非効率になります。

進捗バーを表示させると最初は早いけど後半遅い現象の原因です。


普通はこの場合、ファイル出力等をして対処すると思いますが、今回は違ったアプローチをとりました。
使ったのはコレ↓
pandas.DataFrame.from_dict — pandas 0.22.0 documentation

辞書型のデータからDataFrameを作成する関数 from_dict()
使い方は以下のようになります。

dic = {'index_1':[1,2,3], 'index_2':[4,5,6], 'index_3':[7,8,9]}

df = pd.DataFrame()
df = df.from_dict(dic, orient='index')

#カラム名の設定
df.columns = ['col1', 'col2', 'col3']

orientで辞書型のkeyをどう処理するかが変わります。
orient = 'columns' で辞書のkeyがcolumnに相当するような読み込み
orient = 'index' で辞書のkeyがindexに相当するような読み込み
が出来ます。今回は1行ごとの処理なのでindexを選択

速度の比較としては
最終サイズのDataFrameを作成。locで行ごとに代入 - 12it / s
辞書型に挿入、最後にfrom_dict - 13000it /s

辞書型の方はただの挿入なのでクソ早いです、1000倍
ちなみにappendは平均とかだそうと思ったけど面倒なのでやめました。
メモリに乗り切ればこの方法は有用ですね。

他に方法があればぜひ教えてください!