配列のループ(FOR文)
以下のようなデータがある前提です。
import pandas as pd import numpy as np df = pd.DataFrame(np.random.rand(100000).reshape(100000, 1)) print(df.tail()) # 0 # 99995 0.879119 # 99996 0.600798 # 99997 0.324799 # 99998 0.743424 # 99999 0.520695
普通にdf.iterrows()を使ってループする
%%time a = 0 for index, row in df.iterrows(): a += row[0] print(a) # 50045.80276582274 # CPU times: user 6.9 s, sys: 54.8 ms, total: 6.95 s # Wall time: 7.11 s
df.valuesでNumPy配列でループする
%%time a = 0 for val in df.values: a += val print(a) # [50045.80276582] # CPU times: user 175 ms, sys: 5.27 ms, total: 180 ms # Wall time: 187 ms
Pandasデータフレームに比べると、圧倒的な処理速度です。
df.valuesでNumPy配列でenumerateを使ってループする
%%time a = 0 for index, val in enumerate(df.values): a += val print(a) # [50045.80276582] # CPU times: user 176 ms, sys: 4.7 ms, total: 181 ms # Wall time: 184 ms
enumerateを使っても、パフォーマンスの低下は見られませんでした。誤差の範囲で、逆に早くなっています。
結論
Pandasデータフレームのままループさせると異常に遅くなります。
Pandasのデータを利用する場合は、NumPy配列に変換してからループさせた方が格段に処理が早くなります。
enumerateを使ってindexを取得してもパフォーマンスは落ちませんでした。
ループで配列に値を追加
Pandasデータフレームにappendで要素を追加
%%time df = pd.DataFrame() for i in range(1,10000): df = df.append({0 : i}, ignore_index=True) print(len(df)) print(df.head()) # 9999 # 0 # 0 1.0 # 1 2.0 # 2 3.0 # 3 4.0 # 4 5.0 # CPU times: user 13.8 s, sys: 104 ms, total: 13.9 s # Wall time: 14 s
リスト型にappendで要素を追加
%%time data = [] for i in range(1,10000): data.append(i) print(len(data)) print(data[:5]) # 9999 # [1, 2, 3, 4, 5] # CPU times: user 2.36 ms, sys: 356 µs, total: 2.71 ms # Wall time: 3.18 ms
Pandasデータフレームに比べると、圧倒的な処理速度です。
二次元配列のリスト型にappendで要素を追加
%%time data = [[]] for i in range(1,10000): data.append([i]) print(len(data)) print(data[:5]) # 10000 # [[], [1], [2], [3], [4]] # CPU times: user 4.86 ms, sys: 1.56 ms, total: 6.42 ms # Wall time: 6.39 ms
一次元に比べて、倍ほどの処理時間を要していますが、Pandasデータフレームに比べるとやはり格段に早いです。
辞書型(dict)にupdateで要素を追加
%%time data = {} for i in range(1,10000): data.update({i : i}) print(len(data)) # 9999 # CPU times: user 5.76 ms, sys: 996 µs, total: 6.76 ms # Wall time: 6.6 ms
二次元配列のリスト型とパフォーマンスはほとんど変わりません。
Numpyにappendで要素を追加
%%time data = np.array([]) for i in range(1,10000): data = np.append(data, i) print(len(data)) print(data[:5]) # 9999 # [1. 2. 3. 4. 5.] # CPU times: user 111 ms, sys: 9.94 ms, total: 121 ms # Wall time: 128 ms
リストや辞書型に比べると結構かかっていますが、Pandasデータフレームに比べるとやはり格段に早いです。
二次元のNumpyにappendで要素を追加
%%time data = np.array([[1]]) for i in range(1,10000): data = np.append(data, [[i]], axis=0) print(len(data)) print(data[:5]) # 10000 # [[1] # [1] # [2] # [3] # [4]] # CPU times: user 91.4 ms, sys: 13.7 ms, total: 105 ms # Wall time: 102 ms
何故か一次元より処理速度が早くなっています。誤差の範囲として、二次元配列でもパフォーマンスは変わりないということにしましょう。
結論
FOR文(ループ)と同じように、リスト型が圧倒的な早さを見せています。
辞書型(dict)はリスト型より倍ほど遅いですが、それでも他より格段に早いです。
処理速度の順位
- リスト型
- 辞書型(dict)
- Numpy
- Pandasデータフレーム*めちゃめちゃ遅いので使わない方がいいですね。
コメント