检查一个数组中的所有行是否存在于另一个更大的数组中

时间:2018-01-18 14:28:17

标签: python arrays numpy

我有一个很大的numpy数组

X= np.random.rand(1000,1000)

然后我有一个较小的numpy数组,在这个例子中可以由

生成
Y =X [[3,7,921],:]

我想以编程方式检查Y的所有行是否都在X

解决方案应该很好地扩展。 可能不需要额外的依赖。

灵感来自:Get intersecting rows across two 2D numpy arrays

到目前为止,我已经尝试过:

np.all([s in set([tuple(X) for x in X]) for s in set([tuple(y) for y in Y])])

但我的逻辑必须有缺陷,因为我应该False <{1}} True

1 个答案:

答案 0 :(得分:2)

这是views -

的一种方法
# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

X1D, Y1D = view1D(X,Y)
out = np.in1d(X1D, Y1D).sum() == len(Y1D)

示例运行 -

In [66]: X = np.random.rand(1000,1000)

In [67]: Y = X [[3,7,921],:]

In [68]: X1D, Y1D = view1D(X,Y)

In [69]: np.in1d(X1D, Y1D).sum() == len(Y1D)
Out[69]: True

In [70]: Y[2] = 1

In [71]: X1D, Y1D = view1D(X,Y)

In [72]: np.in1d(X1D, Y1D).sum() == len(Y1D)
Out[72]: False

基准测试和替代方案

建议的方式似乎很快 -

In [73]: %timeit np.in1d(X1D, Y1D).sum() == len(Y1D)
10000 loops, best of 3: 39.6 µs per loop

我们也可以这样做 - np.in1d(Y1D, X1D).all(),但我认为这会迭代X1D的元素,以便在Y1D中进行匹配。现在,在我们的例子中,似乎X1D,即X是一个更大的数组,所以这比使用np.in1d(X1D, Y1D)计算更重,就像之前提出的那样 -

In [84]: %timeit np.in1d(Y1D, X1D)
100 loops, best of 3: 5.82 ms per loop

In [85]: %timeit np.in1d(X1D, Y1D)
10000 loops, best of 3: 34.1 µs per loop

因此,替代解决方案会更慢 -

In [79]: %timeit np.in1d(Y1D, X1D).all()
100 loops, best of 3: 5.99 ms per loop