2017-07-18 84 views
3

我的數據框看起來像這樣填寫列列hold,其值如下計算:使用在列,且前值的大熊貓一些計算

我取hold列中的先前值,並從列中減去當前單元格的相應值cons並從列supply中添加相應的值。

(對於在對應於scale = 1hold的細胞將是(300 - 20) + 0 = 280, 爲下一個單元(280 - 30) + 70) = 320,對下一個單元(320 - 25) + 0) = 295等)

如果在列hold值小於比列s_res中的相應值,然後到下一個單元,我必須加上列s_resz_res列中的對應的下一個單元值之間的差值。

例如,hold列中的值是295,其中scale = 3。該值小於列s_res = 400中的值。然後我需要計算下一個值:(295 - 15) + 0 + (300 - 100) = 480。並且在s_resz_res之間的這個差值寫在add.supply列中。

我需要hold列中的每個新計算值檢查它是否小於s_res列中的值。

結果應該是這樣的:

scale cons hold supply add.supply  s_res  z_res 
48 -5  NaN NaN  NaN  NaN   NaN  NaN 
49 -4  NaN NaN  NaN  NaN   NaN  NaN 
50 -3  NaN NaN  NaN  NaN   NaN  NaN 
51 -2  NaN NaN  NaN  NaN   NaN  NaN 
52 -1  NaN NaN  NaN  NaN   NaN  NaN 
53 0  0  300  0  NaN   100  200 
54 1  20  280  0  NaN   200  322 
55 2  30  320  70  NaN   100  100 
56 3  25  295  0  NaN   400  110 
57 4  15  480  0  200   100  300 
58 5  10  470  0  NaN   100  180 
59 6  40  430  0  NaN   100  100 
... 

我會的任何意見表示感謝。

UPD我試圖代碼

df['hold'] = df.hold.fillna(method='ffill') - df.cons.cumsum() + df.supply.cumsum() 
df['add.supply'] = np.where(df.hold.shift() < df.s_res.shift(), df.z_res - df.s_res, np.nan) 
df['hold'] = df.hold + df['add.supply'].fillna(0).cumsum() 

適用於更大的數據幀,我有問題

我的新數據幀

scale cons hold supply add.supply s_res z_res 
0 0  0 300  0  NaN  100  200 
1 1  20 NaN  0  NaN  200  322 
2 2  30 NaN 70  NaN  100  100 
3 3  25 NaN  0  NaN  400  110 
4 4  15 NaN  0  NaN  100  300 
5 5  10 NaN  0  NaN  100  180 
6 6  40 NaN  0  NaN  100  100 
7 7  60 NaN  0  NaN  300  400 
8 8  50 NaN  0  NaN  245  300 
9 9  70 NaN  0  NaN  300  600 
10 10  50 NaN  0  NaN  143  228 
... 

結果應該是以下:

scale cons hold supply add.supply s_res z_res 
0 0  0 300  0  NaN  100  200 
1 1  20 280  0  NaN  200  322 
2 2  30 320 70  NaN  100  100 
3 3  25 295  0  NaN  400  110 
4 4  15 480  0  200  100  300 
5 5  10 470  0  NaN  100  180 
6 6  40 430  0  NaN  100  100 
7 7  60 370  0  NaN  300  400 
8 8  50 320  0  NaN  245  300 
9 9  70 250  0  NaN  300  600 
10 10  50 285  0   85  143  228 
... 

但代碼執行的結果是不應該的:hold = 370

scale cons hold supply add.supply s_res z_res 
0 0  0 300  0  NaN  100  200 
1 1  20 280  0  NaN  200  322 
2 2  30 320 70  NaN  100  100 
3 3  25 295  0  NaN  400  110 
4 4  15 480  0  200  100  300 
5 5  10 470  0  NaN  100  180 
6 6  40 430  0  NaN  100  100 
7 7  60 370  0  NaN  300  400 
8 8  50 375  0   55  245  300 
9 9  70 605  0  300  300  600 
10 10  50 640  0   85  143  228 
... 

錯誤出現,但我不明白爲什麼。

+1

你能解釋一下你」有沒有試圖做到這一點?這可以幫助人們找到他們最有用的解釋。 – ASGM

+0

@ASGM我道歉,但我恐怕沒有完全理解你的問題。然而,任務的開始會造成最大的困難。我不明白如何使用列'hold'中的前一個值,並且同時從中減去與當前正在計算的單元格相對應的'cons'列中的值。無論如何,計算總是從'scale = 1'的地方開始。我嘗試使用shift(),但我沒有成功。 –

回答

2

而是由行這樣行,你可以使用的cumsum()np.where的組合在整個數據框做到這一點:要在兩個階段做轉換的

df['hold'] = df.hold.fillna(method='ffill') - df.cons.cumsum() + df.supply.cumsum() 
df['add.supply'] = np.where(df.hold.shift() < df.s_res.shift(), df.z_res - df.s_res, np.nan) 
df['hold'] = df.hold + df['add.supply'].fillna(0).cumsum() 

思考。你有一個初始階段,你可以從初始值df.hold中加減。然後,根據某些條件,您在某些情況下正在改變這種新的持有價值。

cumsum()需要一個Series或DataFrame並創建一個新版本,其中每一行是前一行和當前行的累計和。您可以通過df.consdf.supply這樣做來獲取將從df.hold中減去並添加到的累計金額。現在您已經計算出第一階段df.hold

您可以使用np.where找出df.hold何時符合您感興趣的條件。如果符合您的要求,則可以相應地設置df['add.supply']。然後,您可以將此新列添加到df.hold。請注意,我們使用fillna(0)來確保每行都有一個值,並且cumsum()再次用於保留隨時間添加的條件值。

UPDATE

原代碼上面沒有加入add.supply一個值的工作後,由於df.hold第一階段的未來值不包括它。可能有辦法做到這一點不反覆,肯定有比我下面做一個更好的和更清潔的方式,但是這至少會完成這項工作:

df['hold'] = df.hold.fillna(method='ffill') - df.cons.cumsum() + df.supply.cumsum() 

hold = df.hold.tolist() 
s_res = df.s_res.tolist() 
add = (df.z_res - df.s_res).shift(-1).tolist() 

newh = [hold[0]] 
totala = 0 
for h, s, a in zip(hold, s_res, add): 
    newh.append(h + totala) 
    if newh[-1] < s: 
     totala += a 

df['hold'] = pd.Series(newh[1:]) 
df['add.supply'] = np.where(df.hold.shift() < df.s_res.shift(), df.z_res - df.s_res, np.nan) 
+0

感謝您的回答!你可以看看有關的更新嗎?我遇到了結果問題。 –

+0

@YanaDolyuk我看到了這個問題,我正在弄清楚一些事情來解決它。 – ASGM

+1

@YanaDolyuk我爲這個問題提供了一個快速和骯髒的解決方案。我確信有更好的方法來做到這一點 - 但這會完成工作。也許你可以清理它! – ASGM