竹蔵のだいあり - stakezo’s diary

健忘録として。役に立つかな?という情報も

python pandas 処理の高速化、の参考記事をみつけた

とても参考になる記事を見つけたので忘れないように自分用メモ。
秒数について、「参考サイト:27秒」と書いてあるのは参考記事の作者が検証した秒数
「実施秒数:29.183616638183594」と書いてあるのは、実験PCで実施した秒数
ちなみに、記事では約300倍の高速化を実現しており、僕の場合は 29.1836sec -> 0.0758sec
で 385倍 の高速化が実現できました!!すごい!
================================================================================
 
import pandas as pd
import time
df = pd.DataFrame({"a":list(range(500000))})
df.shape # (500000,1)

# start 参考サイト:(a) ナイーブというか公式的(?)な実装
for idx,row in df.iterrows():
    row.a # 参考サイト:27秒
# end 実施秒数:29.183616638183594

# start 参考サイト:(b)ちょっと意識高くしてみた
for idx in range(df.shape[0]):
    df.a.iloc[idx] # 参考サイト:10秒
# end 実施秒数:4.690666437149048

# start 参考サイト:(b') (b)をベースにして、 __getattr__ が殆ど作用しないようにした。
df_a = df.a
for idx in range(df.shape[0]):
    df_a.iloc[idx] # 参考サイト:6.4秒
# end 実施秒数:2.259279489517212

# start (b'') 参考サイト:さらに、 .iloc(これは普通の関数呼び出し)も一個にまとめてみた。
df_a_iloc = df.a.iloc
for idx in range(df.shape[0]):
    df_a_iloc[idx] # 参考サイト:6.2秒
# end 実施秒数:2.0733094215393066

# start 参考サイト:(b''') (b)のdf.aの代わりに df['a'] を使う版
for idx in range(df.shape[0]):
    df["a"].iloc[idx] # 参考サイト:8.9秒
# end 実施秒数:3.5483694076538086

# start 参考サイト:(c) pandasを捨て、numpyに逃げた
for idx in range(df.shape[0]):
    df.a.values[idx] # 参考サイト:2.5秒
# end 実施秒数:2.577686309814453

# start 参考サイト:(c') (c)をベースにして例の __getattr__地獄を回避した
df_a = df.a
for idx in range(df.shape[0]):
    df_a.values[idx] # 参考サイト:0.45秒 (448ms)
# end 実施秒数:0.32686376571655273

start=time.time()
print('start 参考サイト:(c'') (c')からさらに .values 分の __getattr__ も削減')
a = df.a.values
for idx in range(df.shape[0]):
    a[idx] # 参考サイト:0.09秒( 90ms)
print('end',time.time()-start)
# end 実施秒数:0.07588791847229004