如何比较两个 numpy 字符串数组与 "in" 运算符以使用数组广播获取布尔数组?

How to compare two numpy arrays of strings with the "in" operator to get a boolean array using array broadcasting?

Python 允许简单检查一个字符串是否包含在另一个字符串中:

'ab' in 'abcd'

计算结果为 True

现在取一个 numpy 字符串数组,你可以这样做:

import numpy as np
A0 = np.array(['z', 'u', 'w'],dtype=object)

A0[:,None] != A0

生成布尔数组:

array([[False,  True,  True],
       [ True, False,  True],
       [ True,  True, False]], dtype=bool)

现在让我们使用另一个数组:

A1 = np.array(['u_w', 'u_z', 'w_z'],dtype=object)

我想检查 A0 的字符串不包含在 A1 的字符串中的位置,本质上是创建唯一的组合,但以下不会产生布尔数组,只有一个布尔值,无论我如何编写索引:

A0[:,None] not in A1

我也尝试过使用 numpy.in1dnp.ndarray.__contains__,但这些方法似乎也不起作用。

这里的性能是一个问题,所以我想充分利用 numpy's 优化。

如何实现?

编辑:

我发现可以这样做:

fv = np.vectorize(lambda x,y: x not in y)
fv(A0[:,None],A1)

但正如 numpy 文档所述:

The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.

所以这与在数组上循环是一样的,最好不用显式或隐式 for 循环来解决这个问题。

我们可以转换为 string dtype,然后使用其中一个 NumPy based string functions

因此,使用 np.char.count,一种解决方案是 -

np.char.count(A1.astype(str),A0.astype(str)[:,None])==0

替代使用 np.char.find -

np.char.find(A1.astype(str),A0.astype(str)[:,None])==-1

再使用 np.char.rfind -

np.char.rfind(A1.astype(str),A0.astype(str)[:,None])==-1

如果我们将一个转换为 str dtype,我们可以跳过另一个数组的转换,因为无论如何在内部都会完成。所以,最后一个方法可以简化为 -

np.char.rfind(A1.astype(str),A0[:,None])==-1

示例 运行 -

In [97]: A0
Out[97]: array(['z', 'u', 'w'], dtype=object)

In [98]: A1
Out[98]: array(['u_w', 'u_z', 'w_z', 'zz'], dtype=object)

In [99]: np.char.rfind(A1.astype(str),A0[:,None])==-1
Out[99]: 
array([[ True, False, False, False],
       [False, False,  True,  True],
       [False,  True, False,  True]], dtype=bool)

# Loopy solution using np.vectorize for verification
In [100]: fv = np.vectorize(lambda x,y: x not in y)

In [102]: fv(A0[:,None],A1)
Out[102]: 
array([[ True, False, False, False],
       [False, False,  True,  True],
       [False,  True, False,  True]], dtype=bool)