🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

898閲覧

python、5コードを実行し、処理スピードを比較。予想外の結果でした。考えられる理由は何でしょう?

shin_shin

総合スコア96

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/10/09 08:24

編集2019/10/09 08:44

「勝率(勝ち数/総試合数)を計算する」というプログラムを、下記の5つのコードで実行し、その処理スピードを比較する、ということをしています。結果が予想外でしたので、その考察をお聞きしたいです。

5つのパターン
0. 単純なfor文で、一行ずつ処理

  1. df.itterow()で一行ずつ処理
  2. df.ittertuples()で一行ずつ処理
  3. apply関数で、一気に処理
  4. 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

ご教授のほど、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2019/10/10 01:34

考察というかProfileをとって見比べて見るのが一番かと思います。ソースもありますし、内部実装なども見比べるとよりわかりやすくなるかと思います。
guest

回答1

0

ベストアンサー

そもそも、DataFrame.apply()による処理は速くない ということなのではないでしょうか。
「pandas apply performace」で検索すると日本語・英語でいろいろと情報がヒットします。

パターン4のプログラムを以下のように書き換えると、count値として100,000が表示されます。
.apply()を使って書くと1行で書けるけど、全ての行を一気に処理しているわけではなく、行数分ループ処理しているというだけなのでは。

python

1count = 0 2list_win_percentage = [] 3def calc_win_percentage(df): 4 global count 5 count += 1 6 return df["W"] / df["G"] 7 8df["win_percentage"] = df.apply(calc_win_percentage, axis=1) 9print(f'count: {count:,}')

投稿2019/10/09 12:29

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問