是否有一种简单的方法可以根据某种模式在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)
答案 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