如何基于优先级规则匹配DataFrame,实现交易描述分类?
问题描述
给定两个DataFrame:交易数据和分类规则:
import pandas as pd data = {'Transaction_description': ['sfdsjk fsjfdkj;f sfsdf RESTARANT', 'fsdk ;kjf;lskf;m gjkf NL111111111111 klkfdlo', 'golf kjnfksdn DE111111111112 fkdkk', 'jhfjd jhfj Jumbo jhf'], 'Amount': [-20, -21, -30, 10]} Transactions = pd.DataFrame(data) data = { 'Priority': [1, 1, 2, 2, 3, 3], 'Type': ['IBAN', 'IBAN', 'Company', 'Company', 'Keyword','Keyword'], 'Value': ['NL111111111111', 'DE111111111112', 'AMAZON', 'JUMBO','Restaurant','Golf'], 'Description': ['', '', '', '','',''], 'MappingCode': ['A1', 'A2', 'B1', 'B2','B1','B2'] } Categorization = pd.DataFrame(data)
需要按照**优先级顺序(1. IBAN;2. Company;3. Keyword)**匹配Transaction_description字段,为所有交易分配对应的MappingCode,预期结果如下:
data = { 'Transaction_description': ['sfdsjk fsjfdkj;f sfsdf RESTARANT', 'fsdk ;kjf;lskf;m gjkf NL111111111111 klkfdlo', 'golf kjnfksdn DE111111111112 fkdkk', 'jhfjd jhfj Jumbo jhf'], 'Amount': [-20, -21, -30, 10], 'MappingCode': ['B1','A1','A2','B2'] } TransactionsClassified = pd.DataFrame(data)
请问最优雅的实现方式是什么?
优雅实现方案
可以利用pandas的向量化特性和优先级排序逻辑,结合字符串匹配实现高效的规则匹配,以下是两种可行方案:
方案1:迭代匹配(适合小数据集)
先对分类规则按优先级升序排序,确保高优先级规则先被匹配;再对每个交易描述遍历规则,找到第一个匹配的MappingCode立即返回。
import pandas as pd # 初始化数据(省略重复代码) # 1. 按优先级排序,确保高优先级规则在前 Categorization_sorted = Categorization.sort_values('Priority').reset_index(drop=True) # 2. 定义匹配函数:返回第一个匹配的MappingCode def get_mapping_code(desc): desc_lower = desc.lower() for _, row in Categorization_sorted.iterrows(): if row['Value'].lower() in desc_lower: return row['MappingCode'] return None # 无匹配时返回None # 3. 应用到交易数据 Transactions['MappingCode'] = Transactions['Transaction_description'].apply(get_mapping_code)
方案2:向量化匹配(适合大数据集)
通过生成匹配矩阵,利用pandas的向量化操作替代循环,大幅提升处理效率:
import pandas as pd # 初始化数据(省略重复代码) # 1. 按优先级排序 Categorization_sorted = Categorization.sort_values('Priority') # 2. 生成匹配矩阵:每行对应一条规则,每列对应一笔交易,值为是否匹配 matches = Categorization_sorted['Value'].str.lower().apply( lambda x: Transactions['Transaction_description'].str.lower().str.contains(x) ) # 3. 找到每笔交易第一个匹配的规则索引,映射到MappingCode first_match_idx = matches.idxmax(axis=0) Transactions['MappingCode'] = Categorization_sorted.loc[first_match_idx, 'MappingCode'].values
核心逻辑说明
- 排序分类规则:保证高优先级规则先被匹配,避免低优先级规则覆盖正确结果
- 大小写统一:用
lower()实现不区分大小写的匹配,适配交易描述的格式差异 - 提前终止匹配:迭代方案中找到第一个匹配项就返回,向量化方案通过
idxmax直接取第一个匹配的规则索引,都保证了优先级逻辑的正确性
内容的提问来源于stack exchange,提问作者highbury
相关产品推荐
相关产品推荐

