如何用Pandas按月份分组统计各客户订单数(含0值)
如何用Pandas生成各月份所有客户的订单计数(无订单显示0)
实现步骤及代码
首先准备示例数据(可替换为你的真实数据):
import pandas as pd # 构建Customer表 customers = pd.DataFrame({'CustomerID': [1, 2, 3]}) # 构建Orders表示例数据 orders = pd.DataFrame({ 'OrderId': [101, 102, 103, 104], 'CustomerID': [1, 1, 3, 2], 'Date': ['2023-01-05', '2023-01-15', '2023-02-02', '2023-03-10'] }) # 将Date字段转为日期格式,为后续分组做准备 orders['Date'] = pd.to_datetime(orders['Date'])
接下来生成所有客户与所有订单月份的笛卡尔积,确保每个客户在每个月份都有对应记录:
# 提取Orders表中出现过的所有月份,格式为YYYY-MM的周期类型 order_months = orders['Date'].dt.to_period('M').unique() # 生成客户ID和月份的笛卡尔积,作为结果的基础框架 customer_month = pd.MultiIndex.from_product( [customers['CustomerID'], order_months], names=['CustomerID', 'Month'] ).to_frame(index=False)
然后统计每个客户每月的订单数,再与基础框架做左连接,空值填充为0:
# 按客户ID和月份分组,统计订单数量 order_counts = orders.groupby( [orders['CustomerID'], orders['Date'].dt.to_period('M')] ).size().reset_index(name='OrderCount') # 左连接保留所有客户-月份组合,无订单的记录填充0 result = pd.merge( customer_month, order_counts, on=['CustomerID', 'Month'], how='left' ).fillna(0) # 将订单数转为整数类型,贴合业务逻辑 result['OrderCount'] = result['OrderCount'].astype(int)
运行后打印结果,格式如下:
CustomerID Month OrderCount 0 1 2023-01 2 1 1 2023-02 0 2 1 2023-03 0 3 2 2023-01 0 4 2 2023-02 0 5 2 2023-03 1 6 3 2023-01 0 7 3 2023-02 1 8 3 2023-03 0
补充说明
- 如果需要包含Orders表中没有的月份(比如全年12个月无论有无订单都要显示),可以手动生成月份范围:
# 示例:生成2023年1-3月的所有月份 order_months = pd.period_range(start='2023-01', end='2023-03', freq='M') dt.to_period('M')将日期转换为月份周期,比字符串截取更可靠,能避免日期格式不一致的问题- 左连接+
fillna(0)是实现“无订单显示0”的核心逻辑,确保不会遗漏任何客户-月份组合
内容的提问来源于stack exchange,提问作者Simon GIS
相关产品推荐
相关产品推荐

