如何将两个列表的子列表作为单个实体进行比较?
解决numpy数组中子数组整体匹配的问题
你遇到的核心问题是:从df.values提取到的是numpy ndarray,而非普通Python列表,直接用列表的比较逻辑或者numpy元素级的函数,无法实现「将3元素子数组作为单个实体」的匹配判断。下面我会先解释你之前方法失效的原因,再给出两种可行的解决方案:
为什么你的方法没生效?
先逐个分析你尝试的方案:
np.isin(arr1, arr2):这个函数是元素级的检查,会判断arr1里的每个单独元素(比如'AU002')是否在arr2的任意位置,而不是把整个3元素子数组当作一个整体判断,所以返回的mask和arr1形状一致,不是你需要的子数组匹配结果。- 嵌套for循环(i<3/j<3):你的循环逻辑错误,只是交叉对比了前3个位置的元素,没有判断整个子数组的所有元素是否完全相等,自然找不到正确的匹配。
if each == every:each和every是numpy数组,这个比较会返回一个布尔数组(每个元素是否相等),而numpy数组在布尔判断中只要非空就会被视为True,所以这个条件永远成立,导致一直输出"found"。all(elem in arr2 for elem in arr1):numpy的in操作符是检查单个元素是否存在于数组中,而不是检查整个子数组(行)是否存在,所以这个判断本质还是元素级的,不符合你的需求。
解决方案
方法1:转换为元组+集合(高效查找)
因为numpy数组不可哈希,但元组可以,我们可以把每个子数组转换成元组,然后用集合来实现O(1)的快速查找:
import numpy as np # 你的原始数据(转换为numpy数组) arr1 = np.array([['AU002', '000000000037080', 'VB_ADJ'], ['AU002', '000000000037080', 'VB_ADJ'], ['AU002', '000000000039325', 'VB_ADJ'], ['AU002', '000000000039325', 'VB_ADJ']]) arr2 = np.array([['AU002', '000000000037080', 'HUNTER_DOUGLAS'], ['AU002', '000000000037080', 'EXP'], ['AU002', '000000000037080', 'GEN'], ['AU002', '000000000037080', 'VB_ADJ'], ['AU002', '000000000039325', 'EXP']]) # 将arr2的所有行转为元组,存入集合 arr2_tuple_set = set(tuple(row) for row in arr2) # 逐个检查arr1的子数组 for row in arr1: row_tuple = tuple(row) if row_tuple in arr2_tuple_set: print(f"找到: {row_tuple}") else: print(f"未找到: {row_tuple}") # 检查arr1所有元素是否都在arr2中 all_matched = all(tuple(row) in arr2_tuple_set for row in arr1) print(f"\n所有arr1的子数组都在arr2中吗?{all_matched}")
运行后会输出:
找到: ('AU002', '000000000037080', 'VB_ADJ') 找到: ('AU002', '000000000037080', 'VB_ADJ') 未找到: ('AU002', '000000000039325', 'VB_ADJ') 未找到: ('AU002', '000000000039325', 'VB_ADJ') 所有arr1的子数组都在arr2中吗?False
方法2:纯numpy广播实现(无需转换类型)
利用numpy的广播机制,让arr1的每个子数组和arr2的所有子数组做整体比较,然后判断是否存在匹配:
import numpy as np # 你的原始数据 arr1 = np.array([['AU002', '000000000037080', 'VB_ADJ'], ['AU002', '000000000037080', 'VB_ADJ'], ['AU002', '000000000039325', 'VB_ADJ'], ['AU002', '000000000039325', 'VB_ADJ']]) arr2 = np.array([['AU002', '000000000037080', 'HUNTER_DOUGLAS'], ['AU002', '000000000037080', 'EXP'], ['AU002', '000000000037080', 'GEN'], ['AU002', '000000000037080', 'VB_ADJ'], ['AU002', '000000000039325', 'EXP']]) # 对arr1的每一行,检查是否在arr2中存在完全匹配的行 # arr1[:, None] 将arr1转换为(4,1,3)形状,和arr2(5,3)广播为(4,5,3) # np.all(..., axis=2) 判断每一对行的所有元素是否相等,得到(4,5)的布尔数组 # np.any(..., axis=1) 判断arr1的每一行是否在arr2中有匹配 matches = np.any(np.all(arr1[:, None] == arr2, axis=2), axis=1) # 输出结果 for row, is_matched in zip(arr1, matches): status = "找到" if is_matched else "未找到" print(f"{status}: {row}") # 检查所有是否匹配 all_matched = np.all(matches) print(f"\n所有arr1的子数组都在arr2中吗?{all_matched}")
这个方法完全基于numpy的向量操作,适合处理大规模数据,运行结果和方法1一致。
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

