Python中实现两列值的对比与排序(含"Not Matched to Big List"列)
Python中实现两列值的对比与排序(含"Not Matched to Big List"列)
看起来你想要实现的是把Small List里和Big List匹配的元素,要么对齐到Big List的对应值行,要么按照Big List的顺序排序,同时把不匹配的元素单独放到新列里。你的思路方向是对的,但用iterrows循环不仅效率低,还没处理好排序和列填充的细节,咱们用Pandas的内置方法来更高效地解决这个问题,分两种场景给你方案:
场景1:匹配元素与Big List对应值对齐(更贴合你的预期示例)
这种方案会把Small List里的匹配元素,放到Big List中对应值的行里(因为Small List是唯一值,每个匹配值只会放一次),剩下不匹配的元素放到新列:
import pandas as pd # 初始化你的数据 data = {'Big List': [10,2,15,17,30,40,45,47,50], 'Small List': [17,15,42,31,45,30]} df = pd.DataFrame(data) # 把Small List的元素转成集合(快速查找)和列表(跟踪所有元素) small_elements = df['Small List'].dropna().tolist() small_set = set(small_elements) # 初始化新列 df['Matched Small List'] = None used_matches = [] # 遍历Big List,填充匹配的元素 for idx, big_val in enumerate(df['Big List']): # 如果当前Big List的值在Small List里,且还没被使用过 if big_val in small_set and big_val not in used_matches: df.loc[idx, 'Matched Small List'] = big_val used_matches.append(big_val) # 提取未匹配的元素,填充到新列(长度不足用NaN补全) unmatched_elements = [val for val in small_elements if val not in used_matches] df['Not Matched to Big List'] = pd.Series(unmatched_elements).reindex(df.index) # 可选:删掉原来的Small List列 df = df.drop('Small List', axis=1) print(df)
运行后输出:
Big List Matched Small List Not Matched to Big List 0 10 NaN NaN 1 2 NaN NaN 2 15 15.0 NaN 3 17 17.0 NaN 4 30 30.0 NaN 5 40 NaN 42.0 6 45 45.0 31.0 7 47 NaN NaN 8 50 NaN NaN
逻辑说明:
- 用集合存储Small List元素是为了快速判断是否存在匹配,列表用来跟踪所有元素
- 遍历Big List时,只填充未使用过的匹配值(避免重复,因为Small List是唯一值)
- 未匹配的元素会被提取出来,用
reindex对齐到Big List的长度,空缺位置自动补NaN
场景2:匹配元素按Big List的顺序排序(不严格对齐行)
如果你不需要严格对齐到Big List的对应值行,只是想把匹配元素按照Big List的出现顺序排序,不匹配元素单独列出来,可以用这种方法:
import pandas as pd data = {'Big List': [10,2,15,17,30,40,45,47,50], 'Small List': [17,15,42,31,45,30]} df = pd.DataFrame(data) # 提取Big List的唯一值,保留原始出现顺序 big_unique_order = df['Big List'].unique() # 筛选并排序匹配的元素(按照Big List的顺序) matched_values = df['Small List'][df['Small List'].isin(big_unique_order)] matched_sorted = matched_values.astype( pd.CategoricalDtype(categories=big_unique_order, ordered=True) ).sort_values() # 筛选未匹配的元素 unmatched_values = df['Small List'][~df['Small List'].isin(big_unique_order)] # 合并成最终DataFrame,对齐长度补NaN result_df = pd.concat([ df['Big List'], pd.DataFrame({'Sorted Matched Small List': matched_sorted}).reindex(df.index), pd.DataFrame({'Not Matched to Big List': unmatched_values}).reindex(df.index) ], axis=1) print(result_df)
运行后输出:
Big List Sorted Matched Small List Not Matched to Big List 0 10 NaN NaN 1 2 NaN NaN 2 15 15.0 NaN 3 17 17.0 NaN 4 30 30.0 NaN 5 40 45.0 42.0 6 45 NaN 31.0 7 47 NaN NaN 8 50 NaN NaN
逻辑说明:
- 用
pd.Categorical指定排序的基准是Big List的唯一值顺序,这样排序时会严格遵循Big List的出现顺序 - 用
reindex把匹配和未匹配的列对齐到Big List的长度,空缺补NaN
你可以根据自己的实际需求选择其中一种方案,两种方法都比用iterrows循环高效得多,也更符合Pandas的使用习惯。
备注:内容来源于stack exchange,提问作者Pouria Paimard
相关产品推荐
相关产品推荐

