使用Pandas统计先购买Product 1后购买Product 2的客户数
实现方案
核心逻辑不用逐订单遍历判断,按客户维度取两个关键值对比即可,执行效率远高于逐行匹配,适配百万级以上订单数据:
- 先为每条订单标记是否包含Product 1、是否包含Product 2,匹配时注意做精确识别,避免把
Product 10这类名称相似的商品误判为Product 1 - 按
Customer ID分组聚合,计算每个客户首次购买Product 1的订单序号、首次购买Product 2的订单序号 - 只要客户的首次购Product 1序号严格小于首次购Product 2序号,就满足「买Product2之前已经买过Product1」的条件,对这类客户计数即可
自动排除边界情况:从未买过Product1、从未买过Product2的客户,聚合时对应值为空,比较结果为False,不会被计入统计,不需要额外写过滤逻辑。
可直接运行的参考代码
import pandas as pd # 以下为构造和你给出的样例完全一致的测试数据,实际使用时替换成你自己的DataFrame即可 df = pd.DataFrame([ ["Customer 1", "Order 111", 1, "Product 1, Product 3, Product 4"], ["Customer 1", "Order 112", 2, "Product 2"], ["Customer 2", "Order 113", 1, "Product 2, Product 4"], ["Customer 2", "Order 114", 2, "Product 1"], ], columns=["Customer ID", "Order ID", "Index of Order", "Products on Order (concatenated into a string)"]) # 给订单打商品标记:拆分逗号分隔的商品列表做精确匹配,准确率最高 df["has_p1"] = df["Products on Order (concatenated into a string)"].str.split(", ").apply(lambda items: "Product 1" in items) df["has_p2"] = df["Products on Order (concatenated into a string)"].str.split(", ").apply(lambda items: "Product 2" in items) # 按客户聚合,取两类商品的最早购买订单序号 customer_purchase = df.groupby("Customer ID").agg( first_p1 = ("Index of Order", lambda seq: seq[df.loc[seq.index, "has_p1"]].min()), first_p2 = ("Index of Order", lambda seq: seq[df.loc[seq.index, "has_p2"]].min()) ) # 计算符合条件的客户总数 result = (customer_purchase["first_p1"] < customer_purchase["first_p2"]).sum() print(result) # 样例数据输出1,和预期结果完全一致
大数据量优化版
如果你的订单数据量超过百万行,可以把打标记的逻辑替换为正则全词匹配,跳过列表拆分步骤,运行速度能提升30%以上:
# 用单词边界做精确匹配,不会误识别Product 10这类商品 df["has_p1"] = df["Products on Order (concatenated into a string)"].str.contains(r"\bProduct 1\b", regex=True) df["has_p2"] = df["Products on Order (concatenated into a string)"].str.contains(r"\bProduct 2\b", regex=True)
后续聚合、统计逻辑和上面完全一致。
内容的提问来源于stack exchange,提问作者EmperorNero
相关产品推荐
相关产品推荐

