我的数据框如下所示:
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 NaN 0 NaN 200 322
55 2 30 NaN 70 NaN 100 100
56 3 25 NaN 0 NaN 400 110
57 4 15 NaN 0 NaN 100 300
58 5 10 NaN 0 NaN 100 180
59 6 40 NaN 0 NaN 100 100
...
我需要执行以下操作:
从值开始,其中
scale = 1
用如下计算的值填充列 hold
:我取
hold
列中的先前值,并从中减去 cons
列中当前单元格的相应值,然后添加 supply
列中的相应值。(对于对应于
hold
的 scale = 1
列中的单元格,它将是 (300 - 20) + 0 = 280
,对于下一个单元格
(280 - 30) + 70) = 320
,对于下一个单元格 (320 - 25) + 0) = 295
等等)如果
hold
列中的值小于 s_res
列中的相应值,那么我必须将 s_res
和 z_res
列中相应的下一个单元格值之间的差值添加到下一个单元格中。例如,
hold
列中的值为 295
,其中 scale = 3
。该值小于 s_res = 400
列中的值。然后我需要计算下一个值: (295 - 15) + 0 + (300 - 100) = 480
。并将 s_res
和 z_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
...
但是代码执行的结果不是它应该的:
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
...
hold = 370
之后出现错误,但我不明白为什么。 最佳答案
您可以使用 cumsum()
和 np.where
的组合在整个 DataFrame 中执行此操作,而不是逐行执行此操作:
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
的初始值。然后,在某些情况下,您会根据某些条件更改新的 Hold 值。cumsum()
采用 Series 或 DataFrame 并制作一个新版本,其中每一行都是前一行和当前行的累积总和。您可以对 df.cons
和 df.supply
执行此操作,以获得将从 df.hold
中减去和添加的累积量。现在您已经计算了 df.hold
的第一阶段。您可以使用
np.where
找出 df.hold
何时满足您感兴趣的条件。如果满足,您可以相应地设置 df['add.supply']
。然后您可以将此新列添加到 df.hold
。请注意,我们使用 fillna(0)
来确保每一行都有一个值,并再次使用 cumsum()
来随着时间的推移保留添加的条件值。更新
添加
add.supply
的一个值后,上面的原始代码不起作用,因为 df.hold
第一阶段的 future 值尚未包含它。可能有一种方法可以非迭代地执行此操作,并且肯定有比我在下面所做的更好,更清洁的方法,但这至少可以完成工作: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)
关于python - 使用列中的前一个值和 Pandas 中的一些计算填充列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45171500/