如何比较两个 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.in1d
和 np.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)
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.in1d
和 np.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)