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

Pandas双DataFrame按注册日期范围统计用户消费额的实现方案

代码问题根因

你原来的实现存在三个核心逻辑错误,直接导致结果数值错位:

  • 按user分组遍历df1子表时,内部的apply循环没有匹配用户维度,直接在分组里循环全量df2的所有行,完全丢失了用户匹配关系
  • apply返回的结果索引和df2的行索引没有做对齐,赋值时pandas会按索引自动匹配,最终新列的数值根本不是对应用户的计算结果
  • 用固定30天周期计算“注册首月”不符合大多数业务的自然月统计逻辑,遇到大小月、闰月会出现统计偏差
高复用性实现方案

核心思路是先把注册日期关联到每一笔消费记录上,用向量化运算替代逐行循环的apply逻辑,数据量越大效率优势越明显,同时可以灵活扩展不同注册周期的统计需求。

基础预处理

首先要统一日期格式,避免日期运算报错,再把注册日期匹配到每笔交易上:

import pandas as pd

# 统一转换日期列格式
df1['date_1'] = pd.to_datetime(df1['date_1'])
df2['date_2'] = pd.to_datetime(df2['date_2'])

# 左关联匹配每个用户的注册日期到对应交易记录
merged_trade = df1.merge(df2[['user', 'date_2']], on='user', how='left')

# 剔除消费日期早于注册日期的异常数据
merged_trade = merged_trade[merged_trade['date_1'] >= merged_trade['date_2']]

计算消费对应的注册周期

根据业务需要选择两种计算口径,后续扩展统计维度完全不用改核心逻辑:

  1. 自然月口径:比如注册日为2021-02-05,注册首月为2021-02-05到2021-03-04,次月为2021-03-05到2021-04-04
    merged_trade['months_since_register'] = (
        (merged_trade['date_1'].dt.year - merged_trade['date_2'].dt.year) * 12
        + (merged_trade['date_1'].dt.month - merged_trade['date_2'].dt.month)
    )
    
  2. 固定天数口径:比如注册首月为注册后0-30天,次月为31-60天,适合严格按日数算周期的场景
    merged_trade['days_since_register'] = (merged_trade['date_1'] - merged_trade['date_2']).dt.days
    

汇总周期消费并匹配回df2

按用户和周期维度分组求和,就可以得到每个用户不同周期的总消费:

# 以自然月口径为例,按用户、注册后第n月分组汇总
user_period_sum = merged_trade.groupby(
    ['user', 'months_since_register'], as_index=False
)['value'].sum().rename(columns={'value': 'total_amount'})

# 提取注册首月(偏移量为0)的统计结果,匹配回df2
first_month_data = user_period_sum[
    user_period_sum['months_since_register'] == 0
][['user', 'total_amount']]

df2 = df2.merge(first_month_data, on='user', how='left')
# 注册后首月没有消费的用户填充为0
df2['total_amount'] = df2['total_amount'].fillna(0)
df2 = df2.rename(columns={'total_amount': 'first_month_purchase'})
扩展使用说明

后续要统计注册后第二个月、第三个月的消费,只需要调整过滤维度的筛选值即可,不需要重写计算逻辑:

  • 统计注册后第二个月消费:过滤条件换成months_since_register == 1,merge回df2作为新列second_month_purchase
  • 统计固定天数周期的消费:把分组维度换成之前计算的days_since_register,先通过pd.cut按区间分桶打标签,再分组求和即可,逻辑完全通用
    这种向量化的实现方式,在数据量达到十万、百万级时,运行速度比逐行apply的方案快几十到上百倍,不会随着数据增长出现性能瓶颈。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 06:36:04