Python 根据递减值计算新值

Python 根据递减值计算新值,python,pandas,Python,Pandas,问题: import pandas as pd ALLOWANCE = 100 values = pd.Series([85, 10, 25, 30]) desired = pd.Series([0, 0, 20, 30]) 我想做的是,通过不断减少的基数,逐步减少系列中的值 我不确定这方面的术语-我确实认为我可以用cumsum和diff做些什么,但我认为我在这方面做了一场白费力气的追逐 起始代码: import pandas as pd ALLOWANCE = 100 values =

问题:

import pandas as pd

ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])
desired = pd.Series([0, 0, 20, 30])
我想做的是,通过不断减少的基数,逐步减少
系列中的值

我不确定这方面的术语-我确实认为我可以用
cumsum
diff
做些什么,但我认为我在这方面做了一场白费力气的追逐

起始代码:

import pandas as pd

ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])
desired = pd.Series([0, 0, 20, 30])
所需输出:

import pandas as pd

ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])
desired = pd.Series([0, 0, 20, 30])
理由:

import pandas as pd

ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])
desired = pd.Series([0, 0, 20, 30])
余量为基数开始
-
系列
中的每个值都会减少剩余的金额,就像余量本身一样,因此会发生以下步骤:

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

它应该与
一起工作,而
循环:

ii = 0
while (ALLOWANCE > 0 and ii < len(values)):
    if (ALLOWANCE > values[ii]):
        ALLOWANCE -= values[ii]
        values[ii] = 0
    else:
        values[ii] -= ALLOWANCE
        ALLOWANCE = 0
    ii += 1 
ii=0
而(容差>0且ii值[ii]):
容差-=数值[ii]
值[ii]=0
其他:
值[ii]=余量
容差=0
ii+=1

这可能不是很好,但目前这是一种通过以下方式实现的方法:

或者更简单地说:

In [58]:

values.apply(reduce)
Out[58]:
0     0
1     0
2    20
3    30
dtype: int64

您使用
cumsum
diff
的想法行之有效。它看起来不太复杂;不确定是否有更短的解决方案。首先,我们计算累积和,对其进行运算,然后返回(
diff
有点像是
cumsum
的反函数)

导入数学
c=值。总和()-容差
#现在我们有[-15,-5,20,50]
c[c<0]=0#负值在这里没有意义

#(c-c.shift(1))#按照你最初的
cumsum
diff
想法,你可以写:

>>> (values.cumsum() - ALLOWANCE).clip_lower(0).diff().fillna(0)
0     0
1     0
2    20
3    30
dtype: float64
这是
减去余量的累计总和。负值被剪裁为零(因为我们不关心数字,直到我们透支了我们的津贴)。从那里,你可以计算出差异

但是,如果第一个值可能大于公差,则最好采用以下两行变化:

s = (values.cumsum() - ALLOWANCE).clip_lower(0)
desired = s.diff().fillna(s)

这将用“第一个值-余量”值填充第一个
NaN
值。因此,如果
余量
降低到75,它将
所需的
返回为
系列([10,10,25,30])

谢谢。虽然这会起作用,但我也计划在
pandas
中执行其他操作-因此,如果可能的话,我真的想要一个基于
pandas
的解决方案。可能有更好的方法重写我的函数,我不是python专家,我想这可以使用生成器重写,但由于某种原因,它不太管用。理想情况下,如果容差已经为0,我会将其短路,并返回传入的行值。它确实为我指明了正确的方向,并给了我一些想法。。。非常感谢-现在阅读
rolling\u apply
这似乎无法处理
系列
津贴的第一个元素的位置:(@JonClements您只需要附加
.fillna(0)
@EdChum不能这么做-我想我需要使用类似于卡斯滕的答案,如果系列中的第一个值仍然是
85
,而
容差是70,结果是
0
-这是不正确的-应该是
15
我选择了你和卡斯滕的答案的混合-我喜欢
剪辑(lower)()
在这篇文章中,尽管卡斯滕是第一个指出
.fillna(0)
会产生不正确的结果的人。(尽管你已经纠正了这一点-谢谢)我会将
变量重命名为
费用
,将
所需的
变量重命名为
债务
,这与
津贴
相结合,使读者不必看文本就能理解您想要完成的任务。