Python:如何用内置方法查找ndarray中存在于另一ndarray的子数组
在NumPy中查找一个ndarray中包含于另一个ndarray的子数组
嘿,这个需求其实在NumPy里有几种实用的实现方式,我来给你一步步讲清楚:
方法一:利用view和np.in1d(高效推荐)
当你需要判断二维数组的整行是否存在于另一个二维数组时,直接用元素级比较会很麻烦。我们可以把每一行转换成一个连续的字节块视图,这样就能把整行当成单个元素来处理,再用np.in1d快速判断归属:
import numpy as np arr1 = np.array([[1,2], [2,9], [3,7], [5,11], [32,5], [11,4], [89,3], [37,5]]) arr2 = np.array([[12,44], [2,9], [125,3], [37,5]]) # 将每行转换为字节视图,把二维行变成一维"元素" dtype = np.dtype((np.void, arr1.dtype.itemsize * arr1.shape[1])) view1 = arr1.view(dtype).ravel() view2 = arr2.view(dtype).ravel() # 生成掩码:标记arr2中哪些行存在于arr1中 mask = np.in1d(view2, view1) # 获取结果 matching_subarrays = arr2[mask] matching_indices = np.where(mask)[0] print("匹配的子数组:", matching_subarrays) print("在arr2中的索引:", matching_indices)
运行后会输出:
匹配的子数组: [[ 2 9] [37 5]] 在arr2中的索引: [1 3]
这个方法的优势是效率极高,尤其是当数组规模较大时,因为它基于哈希查找,时间复杂度接近O(n)。
方法二:利用广播和all/any(直观易懂)
如果你更喜欢直观的逻辑,可以用NumPy的广播机制来逐行比较:
import numpy as np arr1 = np.array([[1,2], [2,9], [3,7], [5,11], [32,5], [11,4], [89,3], [37,5]]) arr2 = np.array([[12,44], [2,9], [125,3], [37,5]]) # 广播比较:arr2的每一行和arr1的所有行逐一对比 # (arr2[:, None] == arr1) 生成三维数组,最后一维是元素级相等判断 # all(axis=2) 判断整行是否完全相等,any(axis=1) 判断arr2的行是否在arr1中存在 matches = np.any((arr2[:, None] == arr1).all(axis=2), axis=1) # 获取结果 matching_subarrays = arr2[matches] matching_indices = np.where(matches)[0] print("匹配的子数组:", matching_subarrays) print("在arr2中的索引:", matching_indices)
这个方法逻辑清晰,容易理解,但要注意:当arr1和arr2的行数都很多时,会生成一个巨大的三维数组,内存开销会比较大,所以更适合小规模数组。
注意事项
- 两个数组的子数组维度必须一致(比如这里都是二维数组,每行长度都是2),否则上述方法无法直接使用。
- 如果子数组中有浮点数,要小心精度问题——因为浮点数的微小误差会导致匹配失败,这时候可能需要用
np.isclose替代==进行比较。
内容的提问来源于stack exchange,提问作者Kromag
相关产品推荐
相关产品推荐

