Pandas按customer_id统计多列最高频值的实现方法
统计客户最高频购买老花镜度数实现方案
数据集说明
- 核心字段:
customer_id:客户唯一标识order_id:订单唯一标识,对应该客户的历次购买记录order_item1~order_item5:订单内购买的老花镜度数,取值如+1、+4、+2.5等,已移除其他商品冗余信息
- 数据表样例:

已尝试的无效实现
此前编写的两段代码均未得到预期结果:
- 分组组合遍历方案
testdf = testdf.groupby(['customer_id', 'order_id'])['order_item1', 'order_item2', 'order_item3', 'order_item4', 'order_item5']\ .agg(list)\ .apply(lambda x:list(combinations(set(x),2)))\ .explode()
- 按订单分组统计自定义函数方案
def top_product(g): product_cols = [col for col in g.columns if col.startswith('order_item')] try: out = (g[product_cols].stack().value_counts(normalize=True) .reset_index().iloc[0]) out.index = ['most_product'] return out except IndexError: return pd.Series({'order_item': 'None', 'most_product' : 0}) output = testdf.groupby('order_id').apply(top_product)
需求目标
统计每位客户购买频次最高的老花镜度数,例如customer_id为11795的客户,最高频购买的度数为2.5。
正确实现代码
核心逻辑为先将横向存储的订单商品列转为纵向长表,剔除空值后按客户维度统计度数字段的频次,取最高值即可:
import pandas as pd # 提取所有存储老花镜度数的列 item_columns = [col for col in testdf.columns if col.startswith('order_item')] # 宽表转长表,丢弃空的商品记录 long_format_df = testdf.melt( id_vars=['customer_id', 'order_id'], value_vars=item_columns, value_name='degree' ).dropna(subset=['degree']) # 按客户分组,取购买频次最高的度数 customer_top_degree = ( long_format_df.groupby('customer_id')['degree'] # 默认取频次最高的首个值,若有并列第一可调整逻辑返回所有并列值组成的列表 .agg(lambda s: s.value_counts().idxmax()) .reset_index(name='most_purchased_degree') )
若需要处理同客户多个度数频次完全相同的场景,可替换
agg内的逻辑,返回所有频次等于最大值的度数列表。
内容的提问来源于stack exchange,提问作者Bas
相关产品推荐
相关产品推荐

