2017-07-18 74 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