对列执行累积总和,但如果 Pandas 中总和变为负数,则重置为 0

问题描述 投票:0回答:2

我有一个带有这样两列的 pandas 数据框,

Item    Value
0   A   7
1   A   2
2   A   -6
3   A   -70
4   A   8
5   A   0

我想对列进行累计总和,

Value
。但是在创建累积和时,如果该值变为负数,我想将其重置回 0。

我目前正在使用如下所示的循环来执行此操作,

sum_ = 0
cumsum = []

for val in sample['Value'].values:
    sum_ += val
    if sum_ < 0:
        sum_ = 0
    cumsum.append(sum_)

print(cumsum) # [7, 9, 3, 0, 8, 8]

我正在寻找一种更有效的方法来在纯熊猫中执行此操作。

python pandas cumsum
2个回答
9
投票

这可以使用

numpy
来完成,但比
numba
解决方案慢。

sumlm = np.frompyfunc(lambda a,b: 0 if a+b < 0 else a+b,2,1)
newx=sumlm.accumulate(df.Value.values, dtype=np.object)
newx
Out[147]: array([7, 9, 3, 0, 8, 8], dtype=object)

这是

numba
解决方案

from numba import njit
@njit
def cumli(x, lim):
    total = 0
    result = []
    for i, y in enumerate(x):
        total += y
        if total < lim:
            total = 0
        result.append(total)
    return result
cumli(df.Value.values,0)
Out[166]: [7, 9, 3, 0, 8, 8]

1
投票

这只是WeNYoBen的一条评论。

如果您可以避免列出列表,通常建议您避免使用它。

示例

from numba import njit
import numpy as np

#with lists
@njit()
def cumli(x, lim):
    total = 0
    result = []
    for i, y in enumerate(x):
        total += y
        if total < lim:
            total = 0
        result.append(total)
    return result

#without lists
@njit()
def cumli_2(x, lim):
    total = 0.
    result = np.empty_like(x)
    for i, y in enumerate(x):
        total += y
        if total < lim:
            total = 0.
        result[i]=total
    return result

时间

没有 Numba(评论@njit()):

x=(np.random.rand(1_000)-0.5)*5

  %timeit a=cumli(x, 0.)
  220 µs ± 2.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  %timeit a=cumli_2(x, 0.)
  227 µs ± 1.95 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

使用列表或数组没有区别。但如果你即时编译这个函数,情况就不是这样了。

与 Numba:

  %timeit a=cumli(x, 0.)
  27.4 µs ± 210 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  %timeit a=cumli_2(x, 0.)
  2.96 µs ± 32.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

即使在更复杂的情况下(最终数组大小未知,或者只知道最大数组大小),分配一个数组并在最后收缩它通常是有意义的,或者在简单的情况下,甚至运行一次算法来知道最终的结果数组大小并比进行实际计算。

© www.soinside.com 2019 - 2024. All rights reserved.