在numpy数组中搜索模式

时间:2017-01-05 18:27:07

标签: python numpy

是否有一种简单的方法可以根据某种模式在NumPy数组中找到所有相关元素?

例如,请考虑以下数组:

a = array(['zzzz', 'zzzd', 'zzdd', 'zddd', 'dddn', 'ddnz', 'dnzn', 'nznz',
       'znzn', 'nznd', 'zndd', 'nddd', 'ddnn', 'dnnn', 'nnnz', 'nnzn',
       'nznn', 'znnn', 'nnnn', 'nnnd', 'nndd', 'dddz', 'ddzn', 'dznn',
       'znnz', 'nnzz', 'nzzz', 'zzzn', 'zznn', 'dddd', 'dnnd'], dtype=object)

我需要查找包含' ** dd'。

的所有组合

我基本上需要一个函数,它接收数组作为输入并返回一个包含所有相关元素的较小数组:

>> b = func(a, pattern='**dd')
>> b = array(['zzdd', 'zddd', 'zndd', 'nddd', 'nndd', 'dddd'], dtype=object)

5 个答案:

答案 0 :(得分:7)

既然事实证明你实际上正在使用pandas,那么使用vectorized string operations可以更简单的方法在系列级别而不仅仅是ndarray上进行:

In [32]: s = pd.Series(['zzzz', 'zzzd', 'zzdd', 'zddd', 'dddn', 'ddnz', 'dnzn', 'nznz',
    ...:        'znzn', 'nznd', 'zndd', 'nddd', 'ddnn', 'dnnn', 'nnnz', 'nnzn',
    ...:        'nznn', 'znnn', 'nnnn', 'nnnd', 'nndd', 'dddz', 'ddzn', 'dznn',
    ...:        'znnz', 'nnzz', 'nzzz', 'zzzn', 'zznn', 'dddd', 'dnnd'])

In [33]: s[s.str.endswith("dd")]
Out[33]: 
2     zzdd
3     zddd
10    zndd
11    nddd
20    nndd
29    dddd
dtype: object

产生一个系列,或者如果你真的坚持一个ndarray:

In [34]: s[s.str.endswith("dd")].values
Out[34]: array(['zzdd', 'zddd', 'zndd', 'nddd', 'nndd', 'dddd'], dtype=object)

如果您愿意,也可以使用正则表达式:

In [49]: s[s.str.match(".*dd$")]
Out[49]: 
2     zzdd
3     zddd
10    zndd
11    nddd
20    nndd
29    dddd
dtype: object

答案 1 :(得分:4)

这是一种使用numpy.core.defchararray.rfind来获取匹配的最后一个索引的方法,然后我们检查该索引是否为2减去每个字符串的长度。现在,每个字符串的长度为4,因此我们会查找4 - 2 = 2的最后一个索引。

因此,实现将是 -

a[np.core.defchararray.rfind(a.astype(str),'dd')==2]

如果字符串长度不相等,我们需要得到长度,减去2然后比较 -

len_sub = np.array(list(map(len,a)))-len('dd')
a[np.core.defchararray.rfind(a.astype(str),'dd')==len_sub]

为了测试这一点,让我们在给定样本的末尾添加一个以dd结尾的较长字符串 -

In [121]: a = np.append(a,'ewqjejwqjedd')

In [122]: len_sub = np.array(list(map(len,a)))-len('dd')

In [123]: a[np.core.defchararray.rfind(a.astype(str),'dd')==len_sub]
Out[123]: array(['zzdd', 'zddd', 'zndd', 'nddd', 'nndd', 'dddd',\
                 'ewqjejwqjedd'], dtype=object)

答案 2 :(得分:3)

我不是numpy专家。但是,我知道你想要创建一个过滤的numpy数组,而不是标准的python数组,并且从python数组转换为numpy数组需要时间和内存,所以选项不好。

不确定是指正则表达式,而是通配符,在这种情况下,正确选择fnmatch模块??dd模式(任何2个字符+ dd到最后)

(替代解决方案将re.match()与[{1}}作为模式)。

我会计算符合您条件的索引,然后使用..dd$来提取子列表:

take

结果:

from numpy import array
import fnmatch

a = array(['zzzz', 'zzzd', 'zzdd', 'zddd', 'dddn', 'ddnz', 'dnzn', 'nznz',
       'znzn', 'nznd', 'zndd', 'nddd', 'ddnn', 'dnnn', 'nnnz', 'nnzn',
       'nznn', 'znnn', 'nnnn', 'nnnd', 'nndd', 'dddz', 'ddzn', 'dznn',
       'znnz', 'nnzz', 'nzzz', 'zzzn', 'zznn', 'dddd', 'dnnd'], dtype=object)

def func(ar,pattern):
    indices = [i for i,x in enumerate(ar) if fnmatch.fnmatch(x,pattern)]
    return ar.take(indices)

print(func(a,"??dd"))

正则表达式版本(当然结果相同):

['zzdd' 'zddd' 'zndd' 'nddd' 'nndd' 'dddd']

答案 3 :(得分:1)

import fnmatch
import numpy as np
a = ['zzzz', 'zzzd', 'zzdd', 'zddd', 'dddn', 'ddnz', 'dnzn', 'nznz',
       'znzn', 'nznd', 'zndd', 'nddd', 'ddnn', 'dnnn', 'nnnz', 'nnzn',
       'nznn', 'znnn', 'nnnn', 'nnnd', 'nndd', 'dddz', 'ddzn', 'dznn',
       'znnz', 'nnzz', 'nzzz', 'zzzn', 'zznn', 'dddd', 'dnnd']


b=[]
for item in a:
    if fnmatch.fnmatch(item, "z*dd"):
        b.append(item)
print b

输出

['zzdd', 'zddd', 'zndd']

答案 4 :(得分:-1)

Python有一个名为.endswith()的内置函数。线索在名称中,它在字符串中查找以括号中的值结尾的任何值。为了做到这一点,你可以做到以下几点:

i = 0
while i < len(a) :
   if a[i].endswith("dd") :
      print(a[i])
   i += 1