问题:
我想做的是逐步减少a中的值,使Series基数持续减少.
我不知道的术语这个-我认为我可以做一些与cumsum和diff,但我觉得我自己领先于白费力气有...
开始代码:
import pandas as pd
ALLOWANCE = 100
values = pd.Series([85, 10, 25, 30])
Run Code Online (Sandbox Code Playgroud)
期望的输出:
desired = pd.Series([0, 0, 20, 30])
Run Code Online (Sandbox Code Playgroud)
理由:
从基数开始ALLOWANCE- 中的每个值Series减少剩余量,以及余量本身,因此执行以下步骤:
85所以它变成了0,我们现在已经15离开了ALLOWANCE10,我们仍然15可用,所以这又变成0了我们5离开了.25- 我们只剩5下了,所以这就成了20现在我们没有进一步的补贴.30,因为没有余量,值仍为30.Ale*_*ley 10
继你最初的想法cumsum和diff,你可以写:
>>> (values.cumsum() - ALLOWANCE).clip_lower(0).diff().fillna(0)
0 0
1 0
2 20
3 30
dtype: float64
Run Code Online (Sandbox Code Playgroud)
这是values减去津贴的累计和.负值被剪切为零(因为在我们透支我们的津贴之前我们不关心数字).从那里,您可以计算差异.
但是,如果第一个值可能大于允许值,则首选以下两行变体:
s = (values.cumsum() - ALLOWANCE).clip_lower(0)
desired = s.diff().fillna(s)
Run Code Online (Sandbox Code Playgroud)
这将NaN使用"first value - allowance"值填充第一个值.因此,在ALLOWANCE降低到75 的情况下,它返回desired为Series([10, 10, 25, 30]).
你的想法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))
Run Code Online (Sandbox Code Playgroud)
这可能不是那么高效,但目前这是熊猫用这样做的方式rolling_apply:
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
Run Code Online (Sandbox Code Playgroud)
或者更简单:
In [58]:
values.apply(reduce)
Out[58]:
0 0
1 0
2 20
3 30
dtype: int64
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
712 次 |
| 最近记录: |