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

如何用Pandas高效为交易数据添加前3个窗口的交易计数字段

Pandas高效实现银行卡交易窗口历史计数统计

问题背景

给定如下银行卡交易数据集:

data = {
    'TRANSACTIONDATETIME': ['1-Jan-23', '2-Jan-23', '3-Jan-23', '4-Jan-23', '4-Jan-23', '5-Jan-23', '2-Jan-23', '3-Jan-23', '8-Jan-23', '9-Jan-23'],
    'CARD_NUM': [123, 123, 123, 123, 123, 123, 234, 234, 234, 234],
    'WINDOW': [1, 1, 2, 2, 2, 3, 1, 1, 4, 4],
    'COUNT_CURRENT_WINDOW': [1, 2, 1, 2, 3, 1, 1, 2, 1, 2]
}

其中WINDOW是单卡交易按48小时划分的分组,COUNT_CURRENT_WINDOW是当前窗口内的交易累计计数。

需求

在不使用循环(保证大数据集处理效率)的前提下,新增3个字段:

  • COUNT_PREV_WINDOW:当前窗口减1对应的窗口内该卡的总交易数
  • COUNT_2WINDOWS_AGO:当前窗口减2对应的窗口内该卡的总交易数
  • COUNT_3WINDOWS_AGO:当前窗口减3对应的窗口内该卡的总交易数

对应窗口无交易时填0,示例输出参考题目给出的结果。

原代码问题分析

原代码直接按CARD_NUM和WINDOW-1分组取最大值,无法正确关联到原数据的每条记录,且未处理窗口不存在时的补0逻辑,导致结果不符合预期。

正确实现方案

方案一:基于Merge的矢量化关联(推荐大数据集)

1. 生成单卡各窗口的总交易数映射表

先按CARD_NUM和WINDOW分组,取每个窗口COUNT_CURRENT_WINDOW的最大值(即该窗口的总交易数):

import pandas as pd

df = pd.DataFrame(data)

# 生成卡-窗口对应的总交易数表
window_totals = df.groupby(['CARD_NUM', 'WINDOW'])['COUNT_CURRENT_WINDOW'].max().reset_index()
window_totals.rename(columns={'COUNT_CURRENT_WINDOW': 'TOTAL_TRANS'}, inplace=True)

2. 关联历史窗口数据

通过多次左连接,分别匹配当前窗口减1、减2、减3的窗口数据,缺失值填充为0:

# 匹配前1个窗口
df = df.merge(
    window_totals.assign(WINDOW=window_totals['WINDOW'] + 1),
    on=['CARD_NUM', 'WINDOW'],
    how='left'
).rename(columns={'TOTAL_TRANS': 'COUNT_PREV_WINDOW'}).fillna(0)

# 匹配前2个窗口
df = df.merge(
    window_totals.assign(WINDOW=window_totals['WINDOW'] + 2),
    on=['CARD_NUM', 'WINDOW'],
    how='left'
).rename(columns={'TOTAL_TRANS': 'COUNT_2WINDOWS_AGO'}).fillna(0)

# 匹配前3个窗口
df = df.merge(
    window_totals.assign(WINDOW=window_totals['WINDOW'] + 3),
    on=['CARD_NUM', 'WINDOW'],
    how='left'
).rename(columns={'TOTAL_TRANS': 'COUNT_3WINDOWS_AGO'}).fillna(0)

方案二:基于字典映射的实现(代码更简洁)

先构建卡-窗口到总交易数的字典,再通过map匹配历史窗口:

import pandas as pd

df = pd.DataFrame(data)

# 生成卡-窗口的总交易数字典
window_totals = df.groupby(['CARD_NUM', 'WINDOW'])['COUNT_CURRENT_WINDOW'].max()
window_map = window_totals.to_dict()

# 匹配各历史窗口,无数据则填0
df['COUNT_PREV_WINDOW'] = df.apply(
    lambda x: window_map.get((x['CARD_NUM'], x['WINDOW'] - 1), 0), axis=1
)
df['COUNT_2WINDOWS_AGO'] = df.apply(
    lambda x: window_map.get((x['CARD_NUM'], x['WINDOW'] - 2), 0), axis=1
)
df['COUNT_3WINDOWS_AGO'] = df.apply(
    lambda x: window_map.get((x['CARD_NUM'], x['WINDOW'] - 3), 0), axis=1
)

两种方案均使用Pandas矢量化操作,无循环,可高效处理大规模数据集。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:17:25