「勝率(勝ち数/総試合数)を計算する」というプログラムを、下記の5つのコードで実行し、その処理スピードを比較する、ということをしています。結果が予想外でしたので、その考察をお聞きしたいです。
5つのパターン
0. 単純なfor文で、一行ずつ処理
- df.itterow()で一行ずつ処理
- df.ittertuples()で一行ずつ処理
- apply関数で、一気に処理
- Numpyでベクトル化して、一気に処理
直感的(常識的)に考えると、処理スピードの速さは、
処理スピード(予想):5>4>3>2>1
実際は、
処理スピード(実際):5>3>1>2>4
になりました。
Numpyの計算とittertuples()の計算が速いことは、予想ができますが、
apply()の計算が単純なfor文よりも遅いという事実は、かなり衝撃的なのですが、
どんな理由が考えられるでしょうか?
apply()での処理が、for文の処理よりも遅いケースというのは、かなり特殊なケースでしょうか?
下記は、実行・比較したコードになります。
データの生成
python
1import pandas as pd 2import numpy as np 3 4#データの生成 5df = pd.DataFrame() 6n_rows = int(1e5) 7df['Team'] = np.random.rand((n_rows)) 8df['W'] = np.random.rand((n_rows)) 9df['G'] = np.random.rand((n_rows)) 10len(df)
python
1%%timeit 2 3# パターン1: 単純なfor文 4list_win_percentage = [] 5for i in range(len(df)): 6 list_win_percentage.append(df.loc[i, "W"]/df.loc[i, "G"]) 7df["win_percentage"] = list_win_percentage
python
1%%timeit 2# パターン2: df.itterow()で一行ずつ処理 3list_win_percentage = [] 4for i, row in df.iterrows(): 5 list_win_percentage.append(row["W"]/row["G"]) 6 7df["win_percentage"] = list_win_percentage
python
1%%timeit 2# パターン3: df.ittertuples()で一行ずつ処理 3list_win_percentage = [] 4for row_tuple in df.itertuples(): 5 list_win_percentage.append(row_tuple.W/row_tuple.G) 6 7df["win_percentage"] = list_win_percentage
python
1%%timeit 2# パターン4: apply関数で、一気に処理 3list_win_percentage = [] 4def calc_win_percentage(df): 5 return df["W"] / df["G"] 6 7df["win_percentage"] = df.apply(calc_win_percentage, 8 axis=1)
python
1%%timeit 2# パターン5: Numpyでベクトル化して、一気に処理 3df_2012["win_percentage"] = df_2012["W"].values/df_2012["G"].values
ご教授のほど、よろしくお願いいたします。
考察というかProfileをとって見比べて見るのが一番かと思います。ソースもありますし、内部実装なども見比べるとよりわかりやすくなるかと思います。
回答1件
あなたの回答
tips
プレビュー