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

如何基于Customer ID和30天时间范围关联DataFrame并标记交易是否存在

问题描述

我有两个DataFrame:

email_date_df

email_id |customer_id| email_date  | email_opened
    001   |  1000     | 03-02-21    |       1
    002   |  1001     | 03-22-21    |       0
    003   |  1002     | 04-02-21    |       1
    004   |  1003     | 05-02-21    |       1

transaction_df

trans_id |customer_id| trans_date  | amount
    001   |  1000     | 03-04-21    |   $10
    002   |  1001     | 04-30-21    |   $24
    003   |  1001     | 05-02-21    |   $14
    004   |  1003     | 04-10-21    |   $149

我需要给每一封发送给客户的邮件,判断该客户在邮件日期后30天内是否产生了交易。之前单纯按customer_id合并两个DataFrame,导致出现大量重复行和冗余数据。有没有办法针对email_date_df的每一行,在transaction_df里查找是否存在符合30天时间范围的交易?

期望输出如下:

email_id |customer_id| email_date  | email_opened  | transaction_witin_30_days
    001   |  1000     | 03-02-21    |       1       |       1
    002   |  1001     | 03-22-21    |       0       |       0
    003   |  1002     | 04-02-21    |       1       |       0
    004   |  1003     | 05-02-21    |       1       |       0
解决方案

可以通过Pandas的日期转换+分组聚合或条件合并+去重聚合实现,避免全量合并带来的冗余,以下是两种可行方案:

方案一:分组聚合匹配(适合中小数据量)

先把每个客户的交易日期整理成列表,再逐个检查邮件日期的30天窗口内是否有匹配交易:

import pandas as pd

# 1. 将日期字符串转为datetime类型,方便时间计算
email_date_df['email_date'] = pd.to_datetime(email_date_df['email_date'], format='%m-%d-%y')
transaction_df['trans_date'] = pd.to_datetime(transaction_df['trans_date'], format='%m-%d-%y')

# 2. 按客户分组,整理每个客户的所有交易日期为列表
customer_trans = transaction_df.groupby('customer_id')['trans_date'].apply(list).reset_index(name='trans_dates')

# 3. 左连接邮件数据和客户交易日期,保留所有邮件记录
email_with_trans = email_date_df.merge(customer_trans, on='customer_id', how='left')

# 4. 定义函数判断当前邮件对应的30天窗口内是否有交易
def check_trans(row):
    if pd.isna(row['trans_dates']):
        return 0
    cutoff = row['email_date'] + pd.Timedelta(days=30)
    return 1 if any(row['email_date'] <= dt < cutoff for dt in row['trans_dates']) else 0

# 5. 生成目标列并更新原DataFrame
email_date_df['transaction_witin_30_days'] = email_with_trans.apply(check_trans, axis=1)

print(email_date_df)

方案二:条件合并去重(适合大数据量)

先合并符合客户+时间条件的记录,再按邮件ID聚合去重,效率更高:

import pandas as pd

# 1. 转换日期格式
email_date_df['email_date'] = pd.to_datetime(email_date_df['email_date'], format='%m-%d-%y')
transaction_df['trans_date'] = pd.to_datetime(transaction_df['trans_date'], format='%m-%d-%y')

# 2. 按客户ID合并,筛选交易日期在邮件日期30天内的记录
matched_records = pd.merge(email_date_df, transaction_df, on='customer_id')
matched_records['within_30'] = (matched_records['trans_date'] - matched_records['email_date']).dt.days.between(0, 30)

# 3. 按邮件ID聚合,判断是否存在符合条件的交易
trans_flag = matched_records.groupby('email_id')['within_30'].any().astype(int).reset_index()

# 4. 合并回原邮件DataFrame,无匹配的记录填充0
email_date_df = email_date_df.merge(trans_flag, on='email_id', how='left').fillna(0)
email_date_df.rename(columns={'within_30': 'transaction_witin_30_days'}, inplace=True)

print(email_date_df)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:48:06