问题:
我想要做的是一步一步地将Series中的值减少一个不断下降的基数。
我不知道这是什么术语--我确实认为我可以用cumsum和diff做点什么,但我想我是在白费力气.
启动代码:
import pandas as pd
ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])期望输出:
desired = pd.Series([0, 0, 20, 30])的基本原理:
从ALLOWANCE的基数开始-- Series中的每个值都会减去剩余的金额,就像备抵本身一样,因此会发生以下步骤:
85,使其成为0,现在15以ALLOWANCE的形式保留下来10,我们仍然有可用的15,因此这个值再次变为0,并且还剩下5。25 --我们只剩下5了,所以这个值变成了20,现在我们没有进一步的备抵了。30,由于没有备抵,所以这个值仍然是30。发布于 2015-02-23 15:34:31
按照您最初对cumsum和diff的想法,您可以编写:
>>> (values.cumsum() - ALLOWANCE).clip_lower(0).diff().fillna(0)
0 0
1 0
2 20
3 30
dtype: float64这是values减去免税额的累计总和。负值被裁剪为零(因为我们不关心数字,直到我们透支了我们的津贴)。从那里,你可以计算出差异。
但是,如果第一个值可能大于津贴,则最好采用以下两行差异:
s = (values.cumsum() - ALLOWANCE).clip_lower(0)
desired = s.diff().fillna(s)这将使用“第一个值-允许”值填充第一个NaN值。因此,在ALLOWANCE降低到75的情况下,它以Series([10, 10, 25, 30])的形式返回desired。
发布于 2015-02-23 15:33:54
你对cumsum和diff的想法是可行的。它看起来并不复杂;不确定是否有更短的解决方案。首先,我们计算累积和,对其进行运算,然后返回(diff是cumsum的反函数)。
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))发布于 2015-02-23 15:28:36
这可能不是很好的表现,但目前这是一种使用rolling_apply的Pandas方式
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或者更简单地说:
In [58]:
values.apply(reduce)
Out[58]:
0 0
1 0
2 20
3 30
dtype: int64https://stackoverflow.com/questions/28676916
复制相似问题