在 numpy 数组中查找包含子字符串的条目?
Finding entries containing a substring in a numpy array?
我试图在一个数组中找到条目,其中包含一个带有 np.where 的子字符串和一个 in 条件:
import numpy as np
foo = "aa"
bar = np.array(["aaa", "aab", "aca"])
np.where(foo in bar)
这只是returns一个空数组。
为什么会这样?
有没有好的替代解决方案?
我们可以使用np.core.defchararray.find
来查找foo
字符串在bar
的每个元素中的位置,如果找不到则return -1
。因此,它可用于通过检查 find
的输出中的 -1
来检测每个元素中是否存在 foo
。最后,我们将使用 np.flatnonzero
来获取匹配项的索引。所以,我们会有一个实现,就像这样 -
np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
样本运行-
In [91]: bar
Out[91]:
array(['aaa', 'aab', 'aca'],
dtype='|S3')
In [92]: foo
Out[92]: 'aa'
In [93]: np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Out[93]: array([0, 1])
In [94]: bar[2] = 'jaa'
In [95]: np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Out[95]: array([0, 1, 2])
您尝试使用 np.where
的方式不正确。 np.where
的第一个参数应该是一个布尔数组,你只是简单地传递一个布尔值。
foo in bar
>>> False
np.where(False)
>>> (array([], dtype=int32),)
np.where(np.array([True, True, False]))
>>> (array([0, 1], dtype=int32),)
问题是 numpy 没有将 in
运算符定义为 element-wise boolean operation。
您可以通过列表理解来完成您想要的事情。
foo = 'aa'
bar = np.array(['aaa', 'aab', 'aca'])
out = [i for i, v in enumerate(bar) if foo in v]
# out = [0, 1]
bar = ['aca', 'bba', 'baa', 'aaf', 'ccc']
out = [i for i, v in enumerate(bar) if foo in v]
# out = [2, 3]
查看一些使用 in
的示例:
In [19]: bar = np.array(["aaa", "aab", "aca"])
In [20]: 'aa' in bar
Out[20]: False
In [21]: 'aaa' in bar
Out[21]: True
In [22]: 'aab' in bar
Out[22]: True
In [23]: 'aab' in list(bar)
看起来 in
与数组一起使用时就像数组是一个列表一样。 ndarray
确实有一个 __contains__
方法,所以 in
有效,但它可能很简单。
但无论如何,请注意 in alist
不检查子字符串。 strings
__contains__
进行子字符串测试,但我不知道任何将测试传播到组件字符串的内置 class。
如 Divakar
所示,有一组 numpy 函数将字符串方法应用于数组的各个元素。
In [42]: np.char.find(bar, 'aa')
Out[42]: array([ 0, 0, -1])
Docstring:
This module contains a set of functions for vectorized string
operations and methods.
The preferred alias for defchararray
is numpy.char
.
对于这样的操作,我认为 np.char
速度与以下操作大致相同:
In [49]: np.frompyfunc(lambda x: x.find('aa'), 1, 1)(bar)
Out[49]: array([0, 0, -1], dtype=object)
In [50]: np.frompyfunc(lambda x: 'aa' in x, 1, 1)(bar)
Out[50]: array([True, True, False], dtype=object)
进一步的测试表明 ndarray
__contains__
在数组的 flat
版本上运行——也就是说,形状不会影响它的行为。
您也可以这样做:
mask = [foo in x for x in bar]
filter = bar[ np.where( mask * bar != '') ]
如果可以使用pandas
,则可以使用str.contains
方法。
import numpy as np
entries = np.array(["aaa", "aab", "aca"])
import pandas as pd
pd.Series(entries).str.contains('aa') # <----
结果:
0 True
1 True
2 False
dtype: bool
该方法还接受更复杂模式的正则表达式:
pd.Series(entries).str.contains(r'a.a')
结果:
0 True
1 False
2 True
dtype: bool
我试图在一个数组中找到条目,其中包含一个带有 np.where 的子字符串和一个 in 条件:
import numpy as np
foo = "aa"
bar = np.array(["aaa", "aab", "aca"])
np.where(foo in bar)
这只是returns一个空数组。
为什么会这样?
有没有好的替代解决方案?
我们可以使用np.core.defchararray.find
来查找foo
字符串在bar
的每个元素中的位置,如果找不到则return -1
。因此,它可用于通过检查 find
的输出中的 -1
来检测每个元素中是否存在 foo
。最后,我们将使用 np.flatnonzero
来获取匹配项的索引。所以,我们会有一个实现,就像这样 -
np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
样本运行-
In [91]: bar
Out[91]:
array(['aaa', 'aab', 'aca'],
dtype='|S3')
In [92]: foo
Out[92]: 'aa'
In [93]: np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Out[93]: array([0, 1])
In [94]: bar[2] = 'jaa'
In [95]: np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Out[95]: array([0, 1, 2])
您尝试使用 np.where
的方式不正确。 np.where
的第一个参数应该是一个布尔数组,你只是简单地传递一个布尔值。
foo in bar
>>> False
np.where(False)
>>> (array([], dtype=int32),)
np.where(np.array([True, True, False]))
>>> (array([0, 1], dtype=int32),)
问题是 numpy 没有将 in
运算符定义为 element-wise boolean operation。
您可以通过列表理解来完成您想要的事情。
foo = 'aa'
bar = np.array(['aaa', 'aab', 'aca'])
out = [i for i, v in enumerate(bar) if foo in v]
# out = [0, 1]
bar = ['aca', 'bba', 'baa', 'aaf', 'ccc']
out = [i for i, v in enumerate(bar) if foo in v]
# out = [2, 3]
查看一些使用 in
的示例:
In [19]: bar = np.array(["aaa", "aab", "aca"])
In [20]: 'aa' in bar
Out[20]: False
In [21]: 'aaa' in bar
Out[21]: True
In [22]: 'aab' in bar
Out[22]: True
In [23]: 'aab' in list(bar)
看起来 in
与数组一起使用时就像数组是一个列表一样。 ndarray
确实有一个 __contains__
方法,所以 in
有效,但它可能很简单。
但无论如何,请注意 in alist
不检查子字符串。 strings
__contains__
进行子字符串测试,但我不知道任何将测试传播到组件字符串的内置 class。
如 Divakar
所示,有一组 numpy 函数将字符串方法应用于数组的各个元素。
In [42]: np.char.find(bar, 'aa')
Out[42]: array([ 0, 0, -1])
Docstring:
This module contains a set of functions for vectorized string operations and methods. The preferred alias fordefchararray
isnumpy.char
.
对于这样的操作,我认为 np.char
速度与以下操作大致相同:
In [49]: np.frompyfunc(lambda x: x.find('aa'), 1, 1)(bar)
Out[49]: array([0, 0, -1], dtype=object)
In [50]: np.frompyfunc(lambda x: 'aa' in x, 1, 1)(bar)
Out[50]: array([True, True, False], dtype=object)
进一步的测试表明 ndarray
__contains__
在数组的 flat
版本上运行——也就是说,形状不会影响它的行为。
您也可以这样做:
mask = [foo in x for x in bar]
filter = bar[ np.where( mask * bar != '') ]
如果可以使用pandas
,则可以使用str.contains
方法。
import numpy as np
entries = np.array(["aaa", "aab", "aca"])
import pandas as pd
pd.Series(entries).str.contains('aa') # <----
结果:
0 True
1 True
2 False
dtype: bool
该方法还接受更复杂模式的正则表达式:
pd.Series(entries).str.contains(r'a.a')
结果:
0 True
1 False
2 True
dtype: bool