使用Polars高效查找存在共同购买商品的唯一客户ID对
使用Polars高效查找存在共同购买商品的唯一客户ID对
嘿,我来给你捋捋怎么用Polars高效搞定这个需求!咱们的目标是找出所有唯一的客户ID对,只要这俩客户买过至少同一件商品就行,对吧?
首先得避开一个大坑:千万别直接做客户ID的笛卡尔积再过滤,那数据量大的时候绝对卡到怀疑人生。咱们换个思路——先抓每个商品对应的所有购买客户,再在每个商品的客户群里生成两两组合,最后去重就好,这样效率高太多了!
具体步骤看这里:
第一步:清理重复记录
首先,同一个客户可能多次买同一件商品,但咱们只需要知道他买过就行,所以先把重复的「客户-商品」组合去掉:
import polars as pl # 假设你的原始数据框叫df unique_cust_prod = df.unique(subset=["CustomerID", "StockCode"])
第二步:按商品分组,收集对应客户
接下来把每个商品对应的所有客户ID攒成一个列表,这样每个商品就对应一个客户集合:
product_cust_groups = unique_cust_prod.group_by("StockCode").agg( pl.col("CustomerID").alias("customers") )
第三步:生成客户对并避免重复
现在对每个商品的客户列表生成两两组合,这里要注意:(A,B)和(B,A)其实是同一个客户对,所以咱们给每个组合排个序,保证小的ID在前,大的在后,这样后续就不会出现重复对了:
customer_pairs = product_cust_groups.with_columns( pl.col("customers") .list.combinations(2) # 生成所有两两组合 .list.map(lambda pair: pl.Series(pair).sort()) # 给每个组合排序 .alias("cust_pairs") ).explode("cust_pairs") # 把列表拆成单独的行
第四步:整理成最终结果
最后把组合拆成两个单独的列,再去重一次(虽然前面排序已经避免了大部分重复,但保险起见),就得到咱们要的唯一客户对了:
final_pairs = customer_pairs.select( pl.col("cust_pairs").list.get(0).alias("CustomerID_1"), pl.col("cust_pairs").list.get(1).alias("CustomerID_2") ).unique()
这个方法的好处是完全利用Polars的矢量化列表操作,而且只在有共同商品的客户之间生成组合,计算量比全量笛卡尔积小N倍,大数据量下也能跑得飞快~
备注:内容来源于stack exchange,提问作者Scott Deerwester
相关产品推荐
相关产品推荐

