python - 使用列中的先前值和 pandas 中的一些计算来填充列

标签 python pandas

我的数据框是这样的:

   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_resz_res .

例如hold列中的值是295 , 其中scale = 3 .该值小于 s_res = 400 列中的值.然后我需要计算下一个值:(295 - 15) + 0 + (300 - 100) = 480 .并写下 s_res 之间的差异和 z_resadd.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/

相关文章:

python - SciKit Learn - SGDClassifier 准确性不佳

Python Pandas 数据帧 : unorderable types: str() > int()

python - "would require ZIP64 extensions") 大压缩文件 : Filesize would require ZIP64 extensions

python - 可以对数据框中的每一列应用百分位切割吗?

datetime - 按日期对Pandas DataFrame进行分组

python - Pandas groupby 每列并为每组添加新列

python - 如何将 pip 命令的结果存储到 Pandas Dataframe 中

python - 我怎样才能使列表理解具有 "or?"

python - SyntaxError : 'break' outside loop, 错误仅在树莓派 3 上给出,而不是在 pc 上

python - C++ 程序需要几分钟来解析大文件,而 python 只需几秒钟即可运行