Pandas实现连续1的累计求和:分组遇0或换组重置计数
实现思路与解决方案
这是一个很常见的序列分组累计问题,用 Pandas 可以通过分组+辅助块ID的方式轻松解决,我来一步步给你讲清楚实现思路和代码:
核心逻辑
我们需要按Name分组,在每个分组内对连续的1进行累计计数,当遇到0或者分组切换时重置计数。关键是先把每个连续的1序列(被0分隔)标记为独立的“块”,然后在每个块内做累计和,同时保留0的原始值。
步骤1:构造示例DataFrame
首先我们把你给出的数据转换成可测试的 Pandas DataFrame:
import pandas as pd # 原始数据 data = [ ["Name_A", "date1", 1], ["Name_A", "date2", 0], ["Name_A", "date3", 1], ["Name_A", "date4", 1], ["Name_A", "date5", 1], ["Name_B", "date6", 1], ["Name_B", "date7", 1], ["Name_B", "date8", 0], ["Name_B", "date9", 1], ] df = pd.DataFrame(data, columns=["Name", "Date", "Value"])
步骤2:标记连续序列的“块ID”
按Name分组后,我们用(Value == 0).cumsum()生成每个连续序列的块ID:
- 每当遇到
0,块ID就会加1,这样每个被0分隔的连续1序列会被分到同一个块里 - 分组切换时,块ID会自动重置(因为
groupby会单独处理每个分组)
# 生成每个分组内的块ID df["block_id"] = df.groupby("Name")["Value"].apply(lambda x: (x == 0).cumsum())
步骤3:计算每个块内的累计和
现在我们按Name和block_id双重分组,对Value做累计和:
- 对于
Value=0的行,累计和自然是0,完全符合需求 - 对于连续的
1,会在同一个块内从1开始递增计数
# 计算最终结果 df["Result"] = df.groupby(["Name", "block_id"])["Value"].cumsum() # 移除辅助列(可选操作) df = df.drop("block_id", axis=1)
最终结果
运行后你会得到完全符合期望的输出:
Name Date Value Result 0 Name_A date1 1 1 1 Name_A date2 0 0 2 Name_A date3 1 1 3 Name_A date4 1 2 4 Name_A date5 1 3 5 Name_B date6 1 1 6 Name_B date7 1 2 7 Name_B date8 0 0 8 Name_B date9 1 1
简化版代码(合并步骤)
如果不想保留辅助列,可以把逻辑合并成一行,更简洁:
df["Result"] = df.groupby("Name")["Value"].apply( lambda x: x.groupby((x == 0).cumsum()).cumsum() )
这个方案逻辑清晰且高效,适合处理大规模的数据集。
内容的提问来源于stack exchange,提问作者Milo Ventimiglia
相关产品推荐
相关产品推荐

