You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python DataFrame中按月统计跨类别重叠的唯一customer_id数量

按月统计多类别交易重叠客户数

我有一个存储金融交易信息的Python DataFrame,包含customer_id、date、product_type等列,每行是客户当月的交易记录,product_type为交易类别。目标是按月统计各类别组合中重叠的唯一customer_id数量,也就是每月内同时进行多类别交易的客户数。比如2022年6月“Category A”有10个唯一客户,“Category B”有6个,需要统计同时属于这两类的客户数。

输入数据示例

customer_idbranch_idproduct_typedate
CustomerId1Branch1Category A2022-06-30 22:47:35
CustomerId2Branch2Category B2022-06-30 22:43:21
CustomerId3Branch3Category A2022-06-30 22:43:04
CustomerId4Branch1Category C2022-06-30 22:42:42
CustomerId5Branch2Category B2022-06-30 22:31:03
CustomerId6Branch3Category A2022-06-30 22:47:35
CustomerId7Branch1Category D2022-06-30 22:43:21
CustomerId8Branch2Category C2022-06-30 22:43:04
CustomerId9Branch3Category E2022-06-30 22:42:42
CustomerId10Branch1Category B2022-06-30 22:31:03

尝试的代码

import pandas as pd
from itertools import combinations

# DataFrame df with transaction information

categories = ["Category A", "Category B", "Category C", "Category D", "Category E"]

combined_tables = pd.DataFrame()

for i in range(1, len(categories) + 1):
    for combo in combinations(categories, i):
        combo_name = ' & '.join(combo)
        filtered_df = df[df['product_type'].isin(combo)]
        
        # Count how many customer_ids overlap in the same category in each month
        grouped = filtered_df.groupby(['year', 'month', 'product_type'])['customer_id'].nunique().reset_index()
        grouped.rename(columns={'customer_id': combo_name}, inplace=True)
        
        if combined_tables.empty:
            combined_tables = grouped
        else:
            combined_tables = combined_tables.merge(grouped, on=['year', 'month', 'product_type'], how='left')

期望结果

希望得到包含year、month、各类别组合列的DataFrame,列值为对应组合中唯一客户数,示例如下:

yearmonthCategory ACategory BCategory CCategory A & Category BCategory A & Category CCategory B & Category CCategory A & Category B & Category C
2022610682531
202277943210
202286572431
202299481320
2022108762210
2022117851210
2022128942110
202319671210
202327581320
202338492431
202346762210
202355671320
202366582431
202377491210

需要覆盖所有类别组合。


解决方案

原代码的问题在于分组时错误包含了product_type,无法正确统计跨类别的重叠客户。正确思路是先聚合每个客户每月的交易类别集合,再判断集合是否包含目标组合,统计符合条件的客户数。

完整代码

import pandas as pd
from itertools import combinations

# 处理日期列,提取年、月
df['date'] = pd.to_datetime(df['date'])
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month

categories = ["Category A", "Category B", "Category C", "Category D", "Category E"]

# 1. 聚合每个客户每月的交易类别集合
customer_month_cats = df.groupby(['year', 'month', 'customer_id'])['product_type'].agg(set).reset_index()
customer_month_cats.rename(columns={'product_type': 'categories'}, inplace=True)

# 2. 生成所有可能的类别组合(从1个到全类别)
all_combos = []
for i in range(1, len(categories)+1):
    all_combos.extend(combinations(categories, i))

# 3. 统计每个年月下,符合各类别组合的客户数
result = customer_month_cats.groupby(['year', 'month']).apply(
    lambda x: pd.Series({
        ' & '.join(combo): x['categories'].apply(lambda s: set(combo).issubset(s)).sum()
        for combo in all_combos
    })
).reset_index()

# 可选:按组合长度排序列(单类别在前,多类别在后)
result = result[['year', 'month'] + sorted(result.columns[2:], key=lambda col: len(col.split(' & ')))]

print(result)

代码说明

  • 日期处理:将date转为datetime类型,提取年、月字段用于分组。
  • 客户-月类别集合:聚合每个客户当月的所有交易类别,用集合存储便于后续子集判断。
  • 类别组合生成:遍历所有组合长度,生成所有可能的类别组合。
  • 组合客户统计:对每个年月分组,判断客户的类别集合是否包含当前组合,统计符合条件的客户数量。
  • 列排序:可选步骤,让单类别列在前,多类别列在后,结果更直观。

内容的提问来源于stack exchange,提问作者Mac_k17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:44:50