PySpark筛选仅购买指定品类的唯一客户ID问题咨询
筛选仅购买过softline品类的客户ID问题解析
原代码的问题
你写的代码只是从行级别过滤出了category为softline的记录,但并没有从客户维度去判断该客户是否只购买过softline品类。比如客户1既买过softline也买过beverages,你的代码会保留客户1的softline行,但实际上我们需要排除这类客户,所以原逻辑无法达到需求。
正确实现思路
要筛选仅购买过softline的客户,核心是从客户ID维度判断:该客户的所有购买记录里,品类只能是softline,没有其他品类。可以通过两种方式实现:
方式一:分组后检查客户的品类集合
按客户ID分组,收集该客户的所有品类,然后判断这个集合是否仅包含softline:
from pyspark.sql import functions as F # 按客户ID分组,收集所有购买过的品类(去重) customer_categories = df.groupBy("customer_id") \ .agg(F.collect_set("category").alias("all_categories")) # 筛选仅包含softline的客户 only_softline_customers = customer_categories.where( F.size(F.array_except(F.col("all_categories"), F.array(F.lit("softline")))) == 0 ) # 如果需要回到原数据的客户记录,可以再关联 result = df.join(only_softline_customers, on="customer_id", how="inner")
方式二:先排除购买过其他品类的客户
先找出所有购买过非softline品类的客户ID,然后从购买过softline的客户中排除这些ID:
from pyspark.sql import functions as F # 找出所有购买过非softline品类的客户ID other_category_customers = df.where(~F.col("category").isin(["softline"])) \ .select("customer_id").distinct() # 从购买过softline的客户中排除上述客户 only_softline_customers = df.where(F.col("category").isin(["softline"])) \ .select("customer_id").distinct() \ .subtract(other_category_customers) # 关联回原数据(如果需要) result = df.join(only_softline_customers, on="customer_id", how="inner")
补充说明
- 第一种方式更直观,直接从客户的全品类集合判断,适合需要查看客户所有品类情况的场景;
- 第二种方式通过排除法,性能可能更优,尤其是当非softline品类的客户数量较少时。
内容的提问来源于stack exchange,提问作者StupendousEnzio
相关产品推荐
相关产品推荐

