Pandas构建按月份统计新老客户采购量的透视表实现问题
月度新老客户采购人数统计实现方案
逻辑框架
整体流程拆分为3个独立步骤,从根源上避免变量错配、标签关联失效的问题:
- 从交易时间字段提取可用于聚合的时间维度要素
- 基于客户全量历史采购记录打新/老客分类标签
- 关联标签回原始交易明细,按月份维度聚合计数生成目标透视表
原代码问题修正对照
- 针对分组统计时的未定义变量错误:所有分组聚合的结果直接赋值为明确列名,不再使用临时变量做reset_index操作,比如将客户采购计数的结果固定存为
total_purchase_cnt列,从根源上避免引用不存在的number_of_purchase类变量 - 针对标签无法关联回原始表的问题:打标签的逻辑全部在独立的客户统计子表上完成,再通过公共键
customer做左连接关联回每一笔交易记录,不会出现用原始表字段错判客户类型的问题 - 针对透视表维度错位的问题:先按「年-月-客户类型」三级维度做去重客户数统计,再通过pivot方法转换为「行=月份、列=客户类型」的目标结构,避免分组逻辑混乱导致的统计值偏差
可复用代码片段
import pandas as pd # 1. 处理时间字段,提取聚合维度 df['payment_date'] = pd.to_datetime(df['payment_date']) df['year_month'] = df['payment_date'].dt.to_period('M') # 生成月份缩写作为行展示维度 df['month_abbr'] = df['payment_date'].dt.strftime('%b') # 2. 按客户维度统计全量采购次数,打分类标签 customer_stats = df.groupby('customer', as_index=False).agg( total_purchase_cnt=('purchase_id', 'nunique') ) # 分类规则:全量采购次数=1为新客,>1为老客 customer_stats['customer_type'] = customer_stats['total_purchase_cnt'].apply( lambda cnt: 'new_customers' if cnt == 1 else 'old_customers' ) # 3. 关联客户标签回原始交易表 df_with_type = df.merge( customer_stats[['customer', 'customer_type']], on='customer', how='left' ) # 4. 聚合计算各月新老客户采购人数 monthly_stats = df_with_type.groupby( ['year_month', 'month_abbr', 'customer_type'] )['customer'].nunique().reset_index(name='cust_cnt') # 5. 生成目标透视表 pivot_result = monthly_stats.pivot( index=['year_month', 'month_abbr'], columns='customer_type', values='cust_cnt' ).reset_index() # 空值补0,避免无采购的月份出现空值 pivot_result = pivot_result.fillna(0)
易错提醒:老客判定基于客户全量历史的累计采购次数,而非单月内的采购次数,否则会将当月内多次下单的新客错判为老客,导致统计偏差。
输出结果说明
- 最终生成的
pivot_result表完全匹配需求结构:行维度为对应年份的月份缩写(避免不同年份同月份缩写的统计混淆),列维度为new_customers、old_customers两类客户的当月采购人数 - 如果不需要区分同月份的不同年份,可以将透视表index中的
year_month字段移除,直接用月份缩写作为行维度,最终会得到按自然月聚合的全量历史统计结果
内容的提问来源于stack exchange,提问作者Luc
相关产品推荐
相关产品推荐

