如何在Pandas DataFrame中按Store分组识别多列无序重复零件条目
嘿,我来帮你解决这个多列零件重复识别的问题!咱们可以分步来实现你要的效果,先看完整代码,再一步步拆解逻辑:
完整解决方案代码
import numpy as np import pandas as pd # 原始数据 dct = { 'inc_num' :[101,102,103,104,105,106,107,108,109,110], 'store' : ['A','A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'], 'part1' : ['oil','oil', 'filter', 'window', 'mirror', 'filter', 'oil', 'coolant', 'wiper', 'oil'], 'part2' : ['light','shaft', np.nan, 'grease', 'oil', 'gas', np.nan, 'wiper', 'oil', 'filter'], 'part3' : ['filter',np.nan, np.nan, np.nan, 'filter', np.nan, np.nan, 'filter', np.nan, np.nan], 'part4' : [np.nan,np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 'light'] } df = pd.DataFrame(dct) # 步骤1:提取每行的所有非NaN零件,转为集合(自动忽略顺序) df['parts'] = df[['part1', 'part2', 'part3', 'part4']].apply(lambda x: set(x.dropna()), axis=1) # 步骤2:按店铺分组,组内按工单编号降序排列(最新工单在前) df_sorted = df.sort_values(['store', 'inc_num'], ascending=[True, False]).reset_index(drop=True) # 步骤3:跟踪重复零件并生成参考编号 seen_parts = {} # 记录每个店铺已出现的零件(后续工单的零件) duplicate_flags = [] reference_entries = [] for idx, row in df_sorted.iterrows(): store = row['store'] current_parts = row['parts'] current_inc = row['inc_num'] # 初始化当前店铺的已见零件集合 if store not in seen_parts: seen_parts[store] = set() # 判断当前工单是否有零件在后续工单中出现 has_duplicate = not current_parts.isdisjoint(seen_parts[store]) duplicate_flags.append(has_duplicate) # 收集参考编号:后续工单中包含当前零件的inc_num refs = [] # 遍历当前行之后的同店铺工单(降序排列,后面的是更早的工单) for later_idx in range(idx + 1, len(df_sorted)): later_row = df_sorted.iloc[later_idx] if later_row['store'] != store: break if not current_parts.isdisjoint(later_row['parts']): refs.append(str(later_row['inc_num'])) # 格式化参考编号,符合你预期的样式 reference_entries.append('(或)'.join(refs) if refs else np.nan) # 将当前工单的零件加入已见集合 seen_parts[store].update(current_parts) # 合并结果并恢复原顺序 df_sorted['duplicate'] = duplicate_flags df_sorted['reference'] = reference_entries result = df_sorted.sort_values('inc_num').reset_index(drop=True).drop('parts', axis=1) print(result)
代码逻辑拆解
1. 提取零件集合
用apply和lambda把每行的非NaN零件提取出来转为集合,这样天然满足“不考虑零件列顺序”的需求——集合不会记录元素的顺序,只关心元素是否存在。
2. 分组排序
按store升序、inc_num降序排列数据,让每个店铺里最新的工单排在最前面。这样我们可以从后往前跟踪已出现的零件,判断当前工单的零件是否在后续更新的工单中重复。
3. 标记重复与生成参考编号
- 用字典
seen_parts记录每个店铺已经处理过的零件(也就是后续工单里的零件),如果当前工单的零件和这个集合有交集,就标记duplicate=True。 - 参考编号的生成:遍历当前行之后的同店铺工单,收集所有包含当前零件的工单编号,格式化为你要的
102(或)103样式。
4. 恢复原顺序
最后按inc_num升序排序,把数据恢复成原始的工单顺序,再删除临时的parts列。
输出结果
运行代码后会得到和你预期完全一致的结果:
inc_num store part1 part2 part3 part4 duplicate reference 0 101 A oil light filter NaN True 102(或)103 1 102 A oil shaft NaN NaN True NaN 2 103 A filter NaN NaN NaN False NaN 3 104 A window grease NaN NaN False NaN 4 105 B mirror oil filter NaN True 106 5 106 B filter gas NaN NaN False NaN 6 107 B oil NaN NaN NaN False NaN 7 108 C coolant wiper filter NaN True 109(或)110 8 109 C wiper oil NaN NaN True 110 9 110 C oil filter NaN light False NaN
内容的提问来源于stack exchange,提问作者nealkaps
相关产品推荐
相关产品推荐

