根据递减值计算新值

2024-06-26 00:02:04 发布

您现在位置:Python中文网/ 问答频道 /正文

问题:

我想做的是一步一步地将Series中的一个值通过一个不断减少的基数逐步减少。在

我不确定这个术语是什么-我想我可以用cumsum和{}做点什么,但我想我在那里开始了一场漫无目的的追逐。。。在

起始代码:

import pandas as pd

ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])

期望输出:

^{pr2}$

理由:

ALLOWANCE开始,Series中的每个值都将减去剩余的量,这也是津贴本身,因此将执行以下步骤:

  • 从100开始,我们可以完全删除85,所以它变成{},现在剩下{}为{}
  • 下一个值是10,我们仍然有15可用,所以这又变成了0,剩下{}。在
  • 下一个值是25-我们只剩下5,所以这变成了20,现在我们没有更多的余量了。在
  • 下一个值是30,由于没有余量,该值保持为30。在

Tags: 代码importpandasas步骤津贴seriespd
3条回答

这可能不是很有效,但目前这是熊猫使用^{}完成此操作的方法:

In [53]:

ALLOWANCE = 100
def reduce(x):
    global ALLOWANCE
    # short circuit if we've already reached 0
    if ALLOWANCE == 0:
        return x
    val = max(0, x - ALLOWANCE)
    ALLOWANCE = max(0, ALLOWANCE - x)
    return val

pd.rolling_apply(values, window=1, func=reduce)
Out[53]:
0     0
1     0
2    20
3    30
dtype: float64

或者更简单地说:

^{pr2}$

按照你最初的想法cumsumdiff,你可以写下:

>>> (values.cumsum() - ALLOWANCE).clip_lower(0).diff().fillna(0)
0     0
1     0
2    20
3    30
dtype: float64

这是values减去允许值的累计和。负值被裁剪为零(因为我们不在乎数字,直到我们透支了津贴)。从那里,你可以计算出差额。在

但是,如果第一个值可能大于允许值,则首选以下两行变化:

^{pr2}$

这将用“first value-allows”值填充第一个NaN值。因此,在ALLOWANCE被降低到75的情况下,它将desired作为Series([10, 10, 25, 30])返回。在

你对cumsumdiff的想法奏效了。它看起来不太复杂;不确定是否有更短的解决方案。首先,我们计算累计和,然后进行运算,然后返回(diff有点像{}的逆函数)。在

import math

c = values.cumsum() - ALLOWANCE
# now we've got [-15, -5, 20, 50]
c[c < 0] = 0 # negative values don't make sense here

# (c - c.shift(1)) # <-- what I had first: diff by accident

# it is important that we don't fill with 0, in case that the first
# value is greater than ALLOWANCE
c.diff().fillna(math.max(0, values[0] - ALLOWANCE))

相关问题 更多 >