看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
在电商、金融或物流系统中,用户可能因网络问题、误操作或恶意行为提交重复订单。识别这些重复项并区分“首次有效订单”和“后续重复订单”对风控、退款策略或用户行为分析至关重要。然而,简单使用 duplicated() 只能标记是否重复,无法直接区分“第一次出现”和“第 N 次重复”。本文将通过一个真实订单场景,教你如何用 pandas 一行链式代码精准标记每条记录是“首次”还是“重复”,并支持按业务规则(如用户+商品+时间窗口)定义重复逻辑。
假设我们有一份订单日志,包含订单ID、用户ID、商品ID和下单时间:
data_str = """order_id,user_id,product_id,order_time
101,1001,P201,2023-03-01 10:05:00
102,1002,P202,2023-03-01 10:07:00
103,1001,P201,2023-03-01 10:08:00
104,1003,P203,2023-03-01 10:10:00
105,1001,P201,2023-03-01 10:12:00
106,1002,P202,2023-03-01 10:15:00
"""
读取数据的代码:
import pandas as pd
from io import StringIO
df = pd.read_csv(StringIO(data_str))
df['order_time'] = pd.to_datetime(df['order_time'])
需求描述:
我们认为“同一用户在同一商品上的多次下单”属于重复行为(忽略订单ID)。需要新增一列 order_type,规则如下:
'first''duplicate'正确结果应如下所示:
order_id user_id product_id order_time order_type
0 101 1001 P201 2023-03-01 10:05:00 first
1 102 1002 P202 2023-03-01 10:07:00 first
2 103 1001 P201 2023-03-01 10:08:00 duplicate
3 104 1003 P203 2023-03-01 10:10:00 first
4 105 1001 P201 2023-03-01 10:12:00 duplicate
5 106 1002 P202 2023-03-01 10:15:00 duplicate
要实现“首次 vs 重复”的标记,关键在于利用 duplicated(keep='first') 的布尔结果:
keep='first' 表示除第一次外,其余重复项为 True~duplicated(keep='first') 即为首次出现的记录我们可以将这个布尔值映射为 'first' / 'duplicate' 字符串。但要注意:必须确保数据按时间排序,否则“首次”可能不是时间上最早的。因此,先按 order_time 排序,再进行去重判断。
代码如下:
import pandas as pd
from io import StringIO
data_str = """order_id,user_id,product_id,order_time
101,1001,P201,2023-03-01 10:05:00
102,1002,P202,2023-03-01 10:07:00
103,1001,P201,2023-03-01 10:08:00
104,1003,P203,2023-03-01 10:10:00
105,1001,P201,2023-03-01 10:12:00
106,1002,P202,2023-03-01 10:15:00
"""
df = (pd.read_csv(StringIO(data_str))
.assign(order_time=lambda x: pd.to_datetime(x['order_time']))
.sort_values('order_time')
.assign(order_type=lambda x: (~x.duplicated(subset=['user_id', 'product_id'], keep='first'))
.map({True: 'first', False: 'duplicate'}))
)
print(df.reset_index(drop=True))
代码分析:
.assign(order_time=...):将时间字符串转为 datetime 类型,便于排序。.sort_values('order_time'):关键步骤!确保按时间顺序处理,使“首次”具有业务意义。.duplicated(subset=[...], keep='first'):基于 user_id + product_id 判断重复,保留首次出现。~ 取反后,首次为 True,重复为 False。.map({True: 'first', False: 'duplicate'}):将布尔值转换为业务标签。整段代码保持链式风格,逻辑清晰且高效。若需扩展(如加入5分钟内才算重复),可先用 groupby + diff() 计算时间间隔,再结合条件判断,但本例展示了最通用的基础模式。
(完)
更新时间:2025-12-06 12:26:43 标签:pandas python 标记 重复订单