2015-10-17 15 views
8

内ILOCソリューションをスピードアップ:私は列BCために、次のロジックを実装したい私は<code>DataFrame</code>を以下しているパンダのデータフレーム

dates = pd.date_range('20150101', periods=4) 
df = pd.DataFrame({'A' : [5,10,3,4]}, index = dates) 

df.loc[:,'B'] = 0 
df.loc[:,'C'] = 0 
df.iloc[0,1] = 10 
df.iloc[0,2] = 3 

print df 

Out[69]: 

      A B C 
2015-01-01 5 10 3 
2015-01-02 10 0 0 
2015-01-03 3 0 0 
2015-01-04 4 0 0 

  • B(k+1) = B(k) - A(k+1)
  • C(k+1) = B(k) + A(k+1)

私は、次のコードを使用してこれを行うことができます。

for i in range (1, df.shape[0]): 
     df.iloc[i,1] = df.iloc[i-1,1] - df.iloc[i,0] 
     df.iloc[i,2] = df.iloc[i-1,1] + df.iloc[i,0] 
print df 

これは与える:私が探している答えである

   A B C 
2015-01-01 5 10 3 
2015-01-02 10 0 20 
2015-01-03 3 -3 3 
2015-01-04 4 -7 1 

を。問題は、これをDataFrameに適用すると、大きなデータセットが遅く実行されることです。非常に遅い。これを達成するより良い方法はありますか?

+1

理由で2番目の「B」 ' 5?それは '0'ではないでしょうか?そして、なぜ13番の代わりに2番目の 'C'15があるのですか? –

+0

おっと!すみません、私の間違いです。更新しました。 –

+0

私は少し質問を変えて、おもちゃの解決策を追加しました... –

答えて

2

このような再帰的なものは、ベクトル化するのが難しい場合があります。 numbaは通常それらをうまく処理します。コードを再配布する必要がある場合は、余分な依存関係を持たない通常のc-extensionsを生成するので、cythonが良い選択です。

In [88]: import numba 

In [89]: @numba.jit(nopython=True) 
    ...: def logic(a, b, c): 
    ...:  N = len(a) 
    ...:  out = np.zeros((N, 2), dtype=np.int64) 
    ...:  for i in range(N): 
    ...:   if i == 0: 
    ...:    out[i, 0] = b[i] 
    ...:    out[i, 1] = c[i] 
    ...:   else: 
    ...:    out[i, 0] = out[i-1,0] - a[i] 
    ...:    out[i, 1] = out[i-1,0] + a[i] 
    ...:  return out 

In [90]: logic(df.A.values, df.B.values, df.C.values) 
Out[90]: 
array([[10, 3], 
     [ 0, 20], 
     [-3, 3], 
     [-7, 1]], dtype=int64) 

In [91]: df[['A','B']] = logic(df.A.values, df.B.values, df.C.values) 

編集: 他の回答に示すように、この問題は実際にあなたは、おそらく使用すべき、ベクトル化することができます。

+0

これはとてもクールです。 –

+0

これはとても涼しいです!私の実際のロジックは上記より少し複雑ですから、私の問題を解決しました。ありがとう。 –

1

は、基本的には、forループのないちょうどあなたの答えである:私はパフォーマンスの問題について知らない

df['B'].iloc[1:] = df['B'].iloc[:-1].values - df['A'].iloc[1:].values 
df['C'].iloc[1:] = df['B'].iloc[:-1].values + df['A'].iloc[1:].values 

、私はそれが速くなるループせずにね。

+0

これは正しくはありませんが、非常に近いように見えます(データセット内のゼロが原因である可能性もありますが)... –

6

トリックベクトル化はすべてをクワンサムとして書き直すことです。

In [11]: x = df["A"].shift(-1).cumsum().shift().fillna(0) 

In [12]: x 
Out[12]: 
2015-01-01  0 
2015-01-02 10 
2015-01-03 13 
2015-01-04 17 
Name: A, dtype: float64 

In [13]: df["B"].cumsum() - x 
Out[13]: 
2015-01-01 10 
2015-01-02  0 
2015-01-03 -3 
2015-01-04 -7 
dtype: float64 

In [14]: df["B"].cumsum() - x + 2 * df["A"] 
Out[14]: 
2015-01-01 20 
2015-01-02 20 
2015-01-03  3 
2015-01-04  1 
dtype: float64 

注:あなたが完全なソリューション3.

1

にその背中を調整する必要があるので、最初の値は特殊なケースである:あなたの結果で

df1 = df[:1] 
df['B'] = df['B'].shift().cumsum()[1:] - df['A'][1:].cumsum() 
df[:1] = df1 
df['C'] = df['B'].shift() + df['A'] 
df[:1] = df1 
df 

      A B C 
2015-01-01 5 10 3 
2015-01-02 10 0 20 
2015-01-03 3 -3 3 
2015-01-04 4 -7 1 
関連する問題