如何在Pandas中为DataFrame逐行应用不同isin操作(无循环)
Pandas无循环实现逐行元素存在性检查
问题场景
需要逐行对比两个二维数组:检查arr2每行的每个元素是否存在于arr1的对应行中,存在标记为1,不存在标记为0,最终输出每行的0/1结果列表。
示例数据
arr1 = [[1, 7, 6, 2, 8], [1, 5, 4, 8], [8, 2, 5]] arr2 = [[8, 1, 5, 0, 7, 2, 9, 4], [0, 1, 8, 5, 3, 4, 7, 9], [9, 2, 0, 6, 8, 5, 3, 7]]
预期结果(以arr2第一行为例)
[1, 1, 0, 0, 1, 1, 0, 0]
原有循环实现
import pandas as pd d1 = pd.DataFrame(arr1) d2 = pd.DataFrame(arr2) for y in range(len(arr1)): print(d2.iloc[y].isin(d1.iloc[y]).astype(int).tolist())
无循环解决方案
利用Pandas的apply方法结合行索引关联,避免显式遍历行:
实现代码
import pandas as pd arr1 = [[1, 7, 6, 2, 8], [1, 5, 4, 8], [8, 2, 5]] arr2 = [[8, 1, 5, 0, 7, 2, 9, 4], [0, 1, 8, 5, 3, 4, 7, 9], [9, 2, 0, 6, 8, 5, 3, 7]] d1 = pd.DataFrame(arr1) d2 = pd.DataFrame(arr2) # 将arr1的每行转换为集合,存储为与行索引对应的Series arr1_row_sets = pd.Series([set(row) for row in arr1], index=d1.index) # 对d2每行应用检查:根据行索引取对应集合,判断元素是否存在并转0/1 result = d2.apply(lambda row: row.isin(arr1_row_sets[row.name]).astype(int), axis=1) # 输出每行的结果列表 for row in result.values.tolist(): print(row)
输出结果
[1, 1, 0, 0, 1, 1, 0, 0] [0, 1, 1, 1, 0, 1, 0, 0] [0, 1, 0, 0, 1, 1, 0, 0]
原理说明
- 先将
arr1的每行转换为集合,集合的成员查询效率远高于列表,提升判断速度; - 用
pd.Series存储这些集合,确保每个集合与原数据的行索引一一对应; - 通过
d2.apply(..., axis=1)逐行处理d2,利用row.name获取当前行的索引,关联到arr1对应的集合,再用isin()完成元素存在性检查,最后转为整数类型的0/1。
这种方法避免了显式的for循环遍历行,更符合Pandas的向量化编程风格,同时保持代码可读性。
内容的提问来源于stack exchange,提问作者Joseph Kirtman
相关产品推荐
相关产品推荐

