Pythonデータフレームを繰り返し処理しているところ、非常に遅いことがわかりました。パンダではすべてをベクトル化しようとしていることを理解していますが、この場合は特に反復する必要があります(または、ベクトル化が可能な場合は、その方法がわかりません)。
ロジックは単純です。2つの列「A」と「B」と結果列「signal」があります。Aが1の場合は、信号を1に設定します。Bが1の場合は、信号を0に設定します。それ以外の場合、信号は以前の信号になります。言い換えると、列Aは「オン」信号、列Bは「オフ」信号、「信号」は状態を表します。
これが私のコードです:
def signals(indata):
numrows = len(indata)
data = pd.DataFrame(index= range(0,numrows))
data['A'] = indata['A']
data['B'] = indata['B']
data['signal'] = 0
for i in range(1,numrows):
if data['A'].iloc[i] == 1:
data['signal'].iloc[i] = 1
elif data['B'].iloc[i] == 1:
data['signal'].iloc[i] = 0
else:
data['signal'].iloc[i] = data['signal'].iloc[i-1]
return data
入力/出力の例:
indata = pd.DataFrame(index = range(0,10))
indata['A'] = [0, 1, 0, 0, 0, 0, 1, 0, 0, 0]
indata['B'] = [1, 0, 0, 0, 1, 0, 0, 0, 1, 1]
signals(indata)
出力:
A B signal
0 0 1 0
1 1 0 1
2 0 0 1
3 0 0 1
4 0 1 0
5 0 0 0
6 1 0 1
7 0 0 1
8 0 1 0
9 0 1 0
この単純なロジックは、ランダムに生成されたデータを含む2000行のデータフレームで実行するのに46秒かかります。
私の問題に対する最も簡単な答えは、データフレームを反復処理している間はデータフレームに書き込まないことでした。numpyでゼロの配列を作成してから、その配列で反復ロジックを実行しました。次に、データフレームの列に配列を書き込みました。
def signals3(indata):
numrows = len(indata)
data = pd.DataFrame(index= range(0,numrows))
data['A'] = indata['A']
data['B'] = indata['B']
out_signal = np.zeros(numrows)
for i in range(1,numrows):
if data['A'].iloc[i] == 1:
out_signal[i] = 1
elif data['B'].iloc[i] == 1:
out_signal[i] = 0
else:
out_signal[i] = out_signal[i-1]
data['signal'] = out_signal
return data
2000行のランダムデータのデータフレームでは、これは46秒(約1,000倍高速)ではなく43ミリ秒しかかかりません。
また、データフレーム列AとBをシリーズに割り当ててから、シリーズを反復処理するバリアントも試しました。これは少し速かった(27ミリ秒)。しかし、速度のほとんどはデータフレームへの書き込みにあるようです。
コールドスピードとdjkの両方の答えは私の解決策(約4.5ms)よりも速かったが、実際には、それが最適ではない場合でも、おそらくシリーズを繰り返すだけだろう。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加