如何使用另一列中的标记停止和重新启动 cumsum
How to stop and restart cumsum using a marker in another column
我有一个 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 并且可能有更快的方法,有什么建议吗?
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 行
得到了不同的值
注意事项2。对于纯粹主义者,额外的组也可以使用 groupby
来计算。在这种情况下,这并不重要。内部组不会在第一个组之后从零开始,但它们的名称不会在输出中的任何地方使用。
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()
,方法决定行的范围,它必须进行累积。
我有一个 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 并且可能有更快的方法,有什么建议吗?
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 行
得到了不同的值注意事项2。对于纯粹主义者,额外的组也可以使用 groupby
来计算。在这种情况下,这并不重要。内部组不会在第一个组之后从零开始,但它们的名称不会在输出中的任何地方使用。
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()
,方法决定行的范围,它必须进行累积。