2017-10-05 25 views
2

私はPythonデータフレームを反復処理しており、非常に遅いと判断しています。私はパンダですべてをベクトル化しようとしていることを理解していますが、この場合は具体的に反復する必要があります(ベクトル化することが可能な場合は、どうすればよいかわかりません)。前の行を参照しながらpandasデータフレームを反復処理する方法はありますか?

ロジックは単純です.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 

この単純な論理は、データフレーム上で実行するために46秒私のコンピュータを取りますランダムに生成されたデータを含む2000行の

答えて

0

で反復処理する必要がいけません。私はnumpyで0の配列を作成し、配列内に反復的なロジックを作成しました。それから、データフレームの列に配列を書きました。ランダムデータの2000行のデータフレームに

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 

46秒(〜速い1,000倍)とは対照的に、これはわずか43ミリ秒かかります。

また、データフレーム列AとBをシリーズに割り当てた後、そのシリーズを反復処理したバリアントを試しました。これは少し速かった(27ミリ秒)。しかし、遅さの大半はデータフレームへの書き込みであると思われます。

coldspeedとdjkの回答はいずれも私の解決策(約4.5ms)よりも速かったですが、実際には最適ではないにしても、おそらくシリーズを繰り返すでしょう。

2
df['signal'] = df.A.groupby((df.A != df.B).cumsum()).transform('head', 1) 

df 
    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 

ロジックがここにAB間の不平等に基づいてグループにあなたのシリーズを分割することを含む、すべてのグループの値がAによって決定されます。

+0

パンダがこの論理ゲート操作をどのように処理したかを観察することは興味深いです。 –

+0

これは本当にきちんとしています、あなたはもう少し詳しく説明できますか? – DJK

+0

これは興味深い解決策ですが、私はより複雑な反復のために自分自身でそのロジックを思いつくことはできません。私は実際にこの種の問題の処理時間を短縮する簡単で簡単に複製可能な方法を探しています。 – karakumy

1

あなたは私の問題への最も簡単な答えはそれを反復しながら、データフレームに書き込めないことだったあなたには、いくつかのブールインデックス作成を行うことができ、すべての

#set condition for A 
indata.loc[indata.A == 1,'signal'] = 1 
#set condition for B 
indata.loc[indata.B == 1,'signal'] = 0 
#forward fill NaN values 
indata.signal.fillna(method='ffill',inplace=True) 
関連する問題