【问题标题】:How to stop and restart cumsum using a marker in another column如何使用另一列中的标记停止和重新启动 cumsum
【发布时间】:2022-01-24 10:23:48
【问题描述】:

我有一个 pandas 数据框,其中的值需要在每个设备的一个周期内累计,但周期结束标记在另一列(一个易于识别的事件行)。 cumsum 必须一直到它找到这个周期结束标记,然后从零(下一行的第一个值)重新开始。

  device_name value end
0   A5         1    False
1   A5         7    False
2   A5         2    True
3   A5         1    False
4   A5         1    False
5   A5         1    False
6   A5         1    True
7   A6         2    False
8   A6         4    False
9   A6         2    False
10  A6         2    True
11  A6         2    False
12  A6         2    False

结果应该是这样的

  device_name value end     total
0   A5         1    False    1  
1   A5         7    False    8
2   A5         2    True     10
3   A5         1    False    1
4   A5         1    False    2
5   A5         1    False    3
6   A5         1    True     4
7   A6         2    False    2
8   A6         4    False    6
9   A6         2    False    8
10  A6         2    True     10
11  A6         2    False    2
12  A6         2    False    4

我尝试了 cumsum,但我无法将一个句点的结尾与另一个句点分开,我可以遍历行,如果我在 df.end.shift(1) 上找到 True,我会忽略最后一个值,但有至少 60000,可能还有更快的方法,有什么建议吗?

【问题讨论】:

  • 您的输出不合逻辑,为什么第 2 行没有累积,而第 10 行有?我会认为第 2 行是错误的,应该是 10,如果不是,请更新问题。
  • 是的,这是一个错误,我更正了它
  • 太好了,谢谢,那么它应该可以按您的预期工作,请告诉我 ;)

标签: python pandas cumsum


【解决方案1】:

IIUC,您希望每组 cumsum 直到您达到 True。然后,这一行之后,重新开始计数。

您可以使用基于“结束”值的额外组(也使用cumsum):

df['total'] = (df.groupby(['device_name',
                           df['end'].shift(1, fill_value=0).cumsum()])
               ['value'].cumsum())

输出:

   device_name  value    end  total
0           A5      1  False      1
1           A5      7  False      8
2           A5      2   True     10
3           A5      1  False      1
4           A5      1  False      2
5           A5      1  False      3
6           A5      1   True      4
7           A6      2  False      2
8           A6      4  False      6
9           A6      2  False      8
10          A6      2   True     10
11          A6      2  False      2
12          A6      2  False      4

注意。请注意,我在第 2 行得到了不同的值

NB.2。对于纯粹主义者,额外的组也可以使用groupby 来计算。在这种情况下,这并不重要。内部组不会在第一个组之后从零开始,但它们的名称不会在输出中的任何地方使用。

【讨论】:

  • 谢谢你,它工作得很好,我仍然需要花一些时间来理解为什么。
  • @PedroSilva 当然,如果有什么不清楚的地方请告诉我 ;)
【解决方案2】:
cnt = 0
def fetch_flag_col(x):
    global cnt
    resp = cnt
    if(x): cnt+=1
    return resp

df["flag"] = df["end"].apply(fetch_flag_col)
df["total"] = df.groupby(["device_name ","flag"])["Value"].cumsum()

我不确定是否有直接的函数或复杂的方法可以使用原生 pandas api 来执行此操作,但使用上述方法可以在 O(n) 时间复杂度内实现所需的结果。

我们正在做的是,创建一个名为 flag 的中间列,这将帮助 .cumsum(),方法决定在什么范围内的行之间,它必须进行累积。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-21
    • 2015-10-03
    • 2019-04-25
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    相关资源
    最近更新 更多