如何在另一DataFrame中匹配同站点特征最相似且不重复的订单行
匹配需求实现方案
核心逻辑
因为要求按Table1的水果顺序依次匹配,且已匹配订单不可复用,所以不能直接用一次性关联的方式,要采用逐行遍历+状态标记的方案:
- 先保留Table2的原始排序,作为匹配数相同时的优先级依据
- 维护一个已使用订单的集合,每次匹配时排除已被占用的订单
- 对每个水果先筛选同站点的未使用订单,计算每个订单的特征匹配数量
- 按「匹配数降序、Table2原始顺序升序」排序,取排序后的第一个有效结果(匹配数≥1),标记订单为已使用后进入下一个水果的匹配
代码实现(Python Pandas 示例)
import pandas as pd # 构造Table1数据 table1 = pd.DataFrame([ ['Apple', 'Sydney', 'A1', 'B1', 'C1'], ['Banana', 'Sydney', 'A1', 'B1', 'C1'], ['Cherry', 'Sydney', 'A1', 'B2', 'C1'], ['Durian', 'Melbourne', 'A1', 'B1', 'C2'], ['Grape', 'Melbourne', 'A2', 'B2', 'C2'] ], columns=['Fruit', 'Site', 'Feature1', 'Feature2', 'Feature3']) # 构造Table2数据,同时保留原始排序字段 table2 = pd.DataFrame([ ['XX', 'Sydney', 'A2', 'B1', 'C1'], ['XY', 'Sydney', 'A1', 'B1', 'C1'], ['XZ', 'Sydney', 'A1', 'B1', 'C2'], ['YY', 'Melbourne', 'A1', 'B1', 'C1'], ['YZ', 'Melbourne', 'A1', 'B1', 'C1'], ['ZZ', 'Melbourne', 'A2', 'B1', 'C1'] ], columns=['Order', 'Site', 'Feature1', 'Feature2', 'Feature3']) table2['original_order'] = table2.index # 初始化状态 used_orders = set() result = [] # 按顺序遍历每个水果 for _, fruit_row in table1.iterrows(): fruit = fruit_row['Fruit'] site = fruit_row['Site'] f1, f2, f3 = fruit_row['Feature1'], fruit_row['Feature2'], fruit_row['Feature3'] # 筛选同站点未使用的订单 available_orders = table2[(table2['Site'] == site) & (~table2['Order'].isin(used_orders))].copy() if available_orders.empty: continue # 计算每个订单的匹配数 available_orders['matches'] = ( (available_orders['Feature1'] == f1).astype(int) + (available_orders['Feature2'] == f2).astype(int) + (available_orders['Feature3'] == f3).astype(int) ) # 过滤掉无匹配的订单,按规则排序 available_orders = available_orders[available_orders['matches'] >= 1] if available_orders.empty: continue available_orders = available_orders.sort_values(by=['matches', 'original_order'], ascending=[False, True]) # 取最优匹配 best_match = available_orders.iloc[0] result.append({ 'Fruit': fruit, 'Order': best_match['Order'], 'Matches': best_match['matches'] }) used_orders.add(best_match['Order']) # 输出结果 result_df = pd.DataFrame(result) print(result_df)
输出结果
运行上述代码得到的结果和你提供的预期完全一致:
| Fruit | Order | Matches |
|---|---|---|
| Apple | XY | 3 |
| Banana | XX | 2 |
| Cherry | XZ | 1 |
| Durian | YY | 2 |
| Grape | ZZ | 1 |
内容的提问来源于stack exchange,提问作者Thelonious Monk
相关产品推荐
相关产品推荐

