【问题标题】:How to optimize conditional cumsum of multiple column如何优化多列的条件累积
【发布时间】:2021-06-14 11:23:56
【问题描述】:

我有如下非常相似的数据框:

      Date        Col1    Col2    Col3 ...
   2020/11/04     -10      0       12
   2020/11/05      31      12      42
   2020/11/07      10      1      -12
   2020/11/08      2      -15      1
   2020/11/09      2       10      0
   .
   .
   .

如果 sum 为负,我的 cumsum 条件是在计算下一行的总和时将其更改为 0。操作的输出应如下所示。

      Date        Col1    Col2    Col3 ...
   2020/11/04       0      0       12
   2020/11/05      31      12      54
   2020/11/07      41      13      42
   2020/11/08      43      0       43
   2020/11/09      45      10      43
   .
   .
   .

我通过在每一行和每一列循环和应用条件来实现这一点,但是对于繁琐的数据,它的性能很差。

columns = diff.columns
    for col in columns:
        if diff.iloc[0].at[col] < 0:
            diff.iloc[0].at[col] = 0
    for i,row in diff.iterrows():
        if not i == diff.first_valid_index():
            prev = diff.index.get_loc(i) - 1
            for col in columns:
                diff.loc[i].at[col] = diff.loc[i].at[col] + diff.iloc[prev].at[col]
                if diff.loc[i].at[col] < 0:
                    diff.loc[i].at[col] = 0

如何在 pandas 中做得更好?

更新 这个线程here 非常相关,我的解决方案是:

def adj_func(x):
    total = 0
    result = []
    for i, y in enumerate(x):
        total += y
        if total < 0:
            total = 0
        result.append(total)
    return result
diff[col_list].apply(adj_func)

【问题讨论】:

  • 如果值为负,则第一行设置值为 0,否则如果 sum 为负

标签: python pandas nested-loops


【解决方案1】:

njit

如果您可以访问 Numba

from numba import njit

@njit
def f(a):
    for i, x in enumerate(a):
        if x < 0:
            a[i:] -= x
    return a

def g(s):
    return f(s.to_numpy().cumsum())

df.assign(**df[['Col1', 'Col2', 'Col3']].apply(g))

         Date  Col1  Col2  Col3
0  2020/11/04     0     0    12
1  2020/11/05    31    12    54
2  2020/11/07    41    13    42
3  2020/11/08    43     0    43
4  2020/11/09    45    10    43

否则,没有 Numba

def h(s):
    a = s.to_numpy().cumsum()
    for i, x in enumerate(a):
        if x < 0:
            a[i:] -= x
    return a

df.assign(**df[['Col1', 'Col2', 'Col3']].apply(h))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2019-10-05
    • 2021-03-30
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    相关资源
    最近更新 更多