Pandas为DataFrame新增列时按行排除当前ID值的优化实现方法
报错原因
- 逻辑取值错误:
axis=1时apply传入的x是整行Series对象,不是单独的ID字段值,直接对Series做成员判断会触发真值歧义报错。 - 方法使用错误:
list.remove()是原地修改方法,返回值为None,既拿不到修改后的数组,还会直接篡改原始的results_02数组。 - 对象引用错误:最初直接赋值
results_02的写法,会让所有行的TEST列引用同一个列表对象,后续任意修改其中一个单元格的列表,所有行都会同步变化。
最优实现方案
不需要用性能低下的apply(axis=1),直接用列表推导式实现,逻辑清晰、运行速度快,还能避免对象引用的坑:
import pandas as pd # 测试数据 data = {'ID': [250274, 244473, 240274, 247178, 248667]} df = pd.DataFrame(data) results_02 = [250274, 244473, 240274, 247178, 248667] # 核心逻辑:逐行遍历ID,生成排除当前ID的新列表,不修改原始数组 df['TEST'] = [[v for v in results_02 if v != curr_id] for curr_id in df['ID']]
运行后输出完全符合预期:
ID TEST 0 250274 [244473, 240274, 247178, 248667] 1 244473 [250274, 240274, 247178, 248667] 2 240274 [250274, 244473, 247178, 248667] 3 247178 [250274, 244473, 240274, 248667] 4 248667 [250274, 244473, 240274, 247178]
特殊场景适配
如果results_02中存在重复ID,且你只需要移除第一个匹配的当前ID,而非全部匹配项,可以用如下写法:
def remove_first_match(arr, val): temp_arr = arr.copy() if val in temp_arr: temp_arr.remove(val) return temp_arr df['TEST'] = [remove_first_match(results_02, curr_id) for curr_id in df['ID']]
注:如果强行要用
apply实现(性能比列表推导式低3~10倍,不推荐),写法如下:df['TEST'] = df.apply(lambda row: [v for v in results_02 if v != row['ID']], axis=1)
内容的提问来源于stack exchange,提问作者FeoJun
相关产品推荐
相关产品推荐

