我的数据框如下所示:

   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 列中的相应值。

(对于对应于 holdscale = 1 列中的单元格,它将是 (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
...

但是代码执行的结果不是它应该的:
   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.consdf.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/

10-16 05:52