如何在忽略索引的情况下使用pandas的isin方法
我完全懂你的痛点!pd.DataFrame.isin()这个方法其实是逐元素判断的——它只会检查每个单元格的值是否在另一个DataFrame的对应列中,而不是判断整行是否完整匹配。这就是为什么你得到的结果和预期不符的原因。
想要实现“检查table1的每一行是否完整存在于table2中”,又不想用join/merge(担心重复数据处理的问题),可以试试下面两种方法:
方法1:将行转为元组,用集合判断(无join/merge)
这种方法的核心是把每行数据转换成不可变的元组,然后利用集合的快速查找特性来判断行是否存在:
import pandas as pd table1 = pd.DataFrame({'a':[1, 2, 5, 3, 4], 'b':['a', 'b', 'e', 'c', 'd']}) table2 = pd.DataFrame({'a':[1, 4, 3, 6, 2], 'b':['a', 'd', 'c', 'f', 'b']}) # 把table2的所有行转成元组,存入集合(集合查找效率高) table2_row_set = set(tuple(row) for row in table2.to_numpy()) # 对table1的每一行判断是否在集合中 table1['row_exists_in_table2'] = table1.apply(lambda x: tuple(x) in table2_row_set, axis=1) print(table1)
输出结果完全符合你的预期:
a b row_exists_in_table2 0 1 a True 1 2 b True 2 5 e False 3 3 c True 4 4 d True
方法2:用merge+indicator(可选,若能接受轻量merge)
如果你只是担心merge会丢失真实重复项,其实可以用merge的indicator参数来标记行的来源,这样既不会丢失重复行,也能准确判断行是否存在:
merged = table1.merge(table2, on=['a', 'b'], how='left', indicator='row_exists') merged['row_exists'] = merged['row_exists'] == 'both' print(merged)
这个方法会保留table1的所有行(包括重复行),row_exists列会标记该行是否在table2中完整存在,完全不用担心误删真实重复项。
为什么原来的isin()不行?
再补充下你原来代码的问题:table1.isin(table2)会分别检查table1['a']的每个值是否在table2['a']中,table1['b']的每个值是否在table2['b']中。比如table1索引1的a=2在table2的a列里,b='b'在table2的b列里,但isin只会返回每个单元格的结果,不会判断这两个值组成的行是否在table2中——这就是它和你需求的核心差异。
内容的提问来源于stack exchange,提问作者Matt W.
相关产品推荐
相关产品推荐

