python(pandas)で巨大なデータフレームを扱っている時、
ある列の値によって、分割したいことが良くあります。
pandasのgroupbyのユーザーガイドを見ていて、良い方法を見つけたのでそれを紹介します。
Iterating through groups
のところに書かれていますが、groupbyした後そのままsumなどの関数を適用するだけでなく、イテレーターとして使うことで、
各グループに対して順番に処理を行えます。
実際にやってみましょう。
とりあえずサンプルのデータフレームを作ります。
import pandas as pd
import numpy as np
df = pd.DataFrame(
np.random.randn(10000, 10),
columns=['x'+str(i) for i in range(10)],
)
df['y'] = np.random.randint(20, size=10000)
これで、長さが1万行、列が11個あるデータフレーム(df)ができました。
これをy列の値(0〜19)によって、20個のデータフレームに分割します。
df_dict = {}
for name, group in df.groupby('y'):
df_dict[name] = group
これで、20個のデータフレームに分割できました。
ちなみに、この方法を知る前は次のように書いていました。
df_dict = {}
for name in set(df.y):
df_dict[name] = df[df.y == name]
コードの量はほとんど同じなのですが、この方法は無駄な比較を何度も行うことになります。
実際、実行時刻を測ってみるとgroupbyを使う方法は、
CPU times: user 7.47 ms, sys: 3.28 ms, total: 10.8 ms
Wall time: 7.71 ms
なのに対して、使わない方法は
CPU times: user 16.4 ms, sys: 1.81 ms, total: 18.2 ms
Wall time: 16.5 ms
となり、倍以上の時間を要しています。