Python:按Person统计DataFrame中连续重复Activity A的分组信息
处理Pandas DataFrame:按用户统计连续Activity A的分组及平均时长
需求说明
给定包含Person、Activity、Time列的DataFrame,需完成两项任务:
- 按
Person统计连续重复次数超过2次的Activity A的分组数量 - 计算这些符合条件分组的平均时长(每组结束时间减开始时间的总和除以分组数)
现有方案存在两个问题:无法按Person正确聚合,且处理700万行数据时性能不足,需要高效可行的解决方案。
原始数据示例
import pandas as pd df = pd.DataFrame({ "Person": ["P1", "P1","P1","P1","P1","P1","P1","P1","P1","P1", "P2", "P2","P2","P2","P2","P2","P2","P2","P2","P2"], "Activity": ["A", "A", "A", "B", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "A", "A", "B", "A", "B", "A"], "Time": ["0", "0", "1", "1", "1", "3", "5", "5", "6", "6", "6", "6", "6", "6", "6", "6", "6", "6", "6", "6"] }) # 先将Time转为数值类型,确保时长计算有效 df["Time"] = df["Time"].astype(int)
目标结果示例
solution = pd.DataFrame({ "Person": ["P1", "P2"], "Activity": ["A", "A"], "Count": [2, 1], "AVGTime": [3, 0] })
高效解决方案
步骤1:标记连续相同Activity的分组
通过判断当前行与上一行的Person或Activity是否变化,生成连续分组的唯一标识:
df["group_id"] = ( (df["Person"] != df["Person"].shift()) | (df["Activity"] != df["Activity"].shift()) ).cumsum()
步骤2:筛选符合条件的分组
按group_id聚合,提取每个分组的关键信息,再筛选出Activity为A且连续次数超过2次的分组:
group_stats = df.groupby("group_id").agg( Person=("Person", "first"), Activity=("Activity", "first"), count=("Activity", "size"), start_time=("Time", "min"), end_time=("Time", "max") ).query("Activity == 'A' and count > 2")
步骤3:按Person聚合计算最终结果
对筛选后的分组按Person和Activity聚合,统计分组数量并计算平均时长:
result = group_stats.groupby(["Person", "Activity"]).agg( Count=("group_id", "count"), total_duration=lambda x: (x["end_time"] - x["start_time"]).sum() ).assign( AVGTime=lambda x: x["total_duration"] / x["Count"] ).reset_index() # 若需要保留所有Person(包括无符合条件分组的),可取消以下注释 # all_persons = df["Person"].unique() # result = result.merge( # pd.DataFrame({"Person": all_persons, "Activity": "A"}), # on=["Person", "Activity"], # how="right" # ).fillna(0) # 调整列顺序匹配目标结果 result = result[["Person", "Activity", "Count", "AVGTime"]]
性能优化说明
- 全程采用Pandas矢量化操作,避免逐行循环,处理700万行数据时效率远高于循环方案
- 先筛选再聚合,大幅减少后续计算的数据量
groupby+agg组合基于底层C实现,是Pandas中最高效的聚合方式之一
验证结果
运行上述代码后,输出与目标结果一致:
print(result) # 输出: # Person Activity Count AVGTime # 0 P1 A 2 3.0 # 1 P2 A 1 0.0
内容的提问来源于stack exchange,提问作者pyEnthusiast90
相关产品推荐
相关产品推荐

