Pandas实现两表按规则匹配扣减errq字段得到期望结果
Pandas实现err/scr表动态额度扣减匹配方案
逻辑前提
之前三种方案输出错误的核心原因是没有实现匹配成功后实时扣减err可用额度、单条scr匹配成功即终止流程的动态规则,全量连接、静态聚合的思路完全不适用这类有先后顺序的额度占用场景。
匹配必须严格遵循以下规则:
- 逐行按scr表的原始顺序处理,不得打乱scr原有排序
- 单条scr的匹配必须同时满足三个条件:
- err记录的
p字段与当前scr的p值完全相等 - err记录的
errd>= 当前scr的scrd - err记录当前剩余可用额度 >= 当前scr需要扣减的
scrq值
- err记录的
- 单条scr匹配到第一条符合要求的err记录后,立刻从对应err的可用额度中扣除本次
scrq值,标记该scr的n为匹配成功,直接跳转处理下一条scr,不得继续匹配其他err记录
可直接运行的实现代码
import pandas as pd # 初始化err表的剩余可用额度字段,初始值和errq一致 err["remain_q"] = err["errq"] # 存储匹配成功的全局唯一n标识 success_n = set() # 按scr原始顺序逐行处理 for _, scr_item in scr.iterrows(): # 快速筛选符合前置条件的候选err记录 candidate_filter = ( (err["p"] == scr_item["p"]) & (err["errd"] >= scr_item["scrd"]) & (err["remain_q"] >= scr_item["scrq"]) ) # 无有效候选直接跳过 if not candidate_filter.any(): continue # 命中第一条符合条件的err记录,执行扣减(如果业务要求按errd最早/最晚优先匹配,可对候选集排序后再取索引) hit_err_index = err[candidate_filter].index[0] err.loc[hit_err_index, "remain_q"] -= scr_item["scrq"] success_n.add(scr_item["n"]) # 输出统计结果 total_match_count = len(success_n) match_detail = scr[scr["n"].isin(success_n)].reset_index(drop=True) final_err_after_deduct = err.copy()
性能优化提示:数据量大于10万行时,可提前将err表按
p字段分组存储为字典格式,key为p字段值,value为对应p值下的err子数据集,每次匹配直接读取对应p的候选集筛选,避免全表扫描,运行效率可提升10~100倍。
原有三种方案的错误点说明
- 遍历scr判断日期范围内errq总和方案:errq是逐次扣减的动态值,静态总和满足要求不代表单条err的剩余额度可满足当前scr扣减需求,且无实际扣减动作,后续匹配会重复占用同一份err额度
- 两表左连接过滤后按n去重方案:全量连接属于静态匹配,没有动态更新err的可用额度,会出现多条scr重复占用同一条err额度的问题,去重逻辑无法解决额度冲突
- 双层嵌套循环逐行匹配方案:未在单条scr匹配成功后立刻跳出内层err遍历循环,会导致单条scr重复扣减多条err额度;同时未提前筛选候选集,每次全量遍历err表导致运行效率极低
内容的提问来源于stack exchange,提问作者user18977534
相关产品推荐
相关产品推荐

