在Numpy数组中查找模式

2024-09-28 20:16:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在一个名为valuesnumpyarray中找到模式。我想返回模式的起始索引位置。我知道我可以在每个元素上迭代并检查该元素和下一个元素是否与模式匹配,但是在一个非常低效的大型数据集上,我正在寻找更好的替代方案。

我有一个使用np.where搜索单个值的工作解决方案,但是我无法让它与查找一个或两个数字一起工作。

示例:

import numpy as np
values = np.array([0,1,2,1,2,4,5,6,1,2,1])
searchval = [1,2]
print  np.where(values == searchval)[0]

输出:

[]

预期产量:

[1, 3, 8]

Tags: 数据importnumpy元素示例np模式方案
3条回答

这是一个使用where的直接方法。从查找匹配项的逻辑表达式开始:

In [670]: values = np.array([0,1,2,1,2,4,5,6,1,2,1])
     ...: searchval = [1,2]
     ...: 
In [671]: (values[:-1]==searchval[0]) & (values[1:]==searchval[1])
Out[671]: array([False,  True, False,  True, False, False, False, False,  True, False], dtype=bool)
In [672]: np.where(_)
Out[672]: (array([1, 3, 8], dtype=int32),)

它可以被概括为一个在多个searchval上操作的循环。正确的切片范围需要一些技巧。在另一个答案中建议的roll可能更容易,但我怀疑有点慢。

只要searchvalvalues小,这种一般方法就应该是有效的。有一个np.in1d进行这种匹配,但是有一个or测试。所以不适用。但它也使用了这种迭代方法,即searchval列表足够小。

广义切片

In [716]: values
Out[716]: array([0, 1, 2, 1, 2, 4, 5, 6, 1, 2, 1])
In [717]: searchvals=[1,2,1]
In [718]: idx = [np.s_[i:m-n+1+i] for i in range(n)]
In [719]: idx
Out[719]: [slice(0, 9, None), slice(1, 10, None), slice(2, 11, None)]
In [720]: [values[idx[i]] == searchvals[i] for i in range(n)]
Out[720]: 
[array([False,  True, False,  True, False, False, False, False,  True], dtype=bool),
 array([False,  True, False,  True, False, False, False, False,  True], dtype=bool),
 array([False,  True, False, False, False, False,  True, False,  True], dtype=bool)]
In [721]: np.all(_, axis=0)
Out[721]: array([False,  True, False, False, False, False, False, False,  True], dtype=bool)
In [722]: np.where(_)
Out[722]: (array([1, 8], dtype=int32),)

我用中间体np.s_来观察切片,确保它们看起来合理。

大步前进

一个高级技巧是使用as_strided构造“rolled”数组并对其执行2d==测试。as_strided很整洁但很棘手。要正确使用它,你必须了解步伐,并得到正确的形状。

In [740]: m,n = len(values), len(searchvals)
In [741]: values.shape
Out[741]: (11,)
In [742]: values.strides
Out[742]: (4,)
In [743]: 
In [743]: M = as_strided(values, shape=(n,m-n+1),strides=(4,4))
In [744]: M
Out[744]: 
array([[0, 1, 2, 1, 2, 4, 5, 6, 1],
       [1, 2, 1, 2, 4, 5, 6, 1, 2],
       [2, 1, 2, 4, 5, 6, 1, 2, 1]])
In [745]: M == np.array(searchvals)[:,None]
Out[745]: 
array([[False,  True, False,  True, False, False, False, False,  True],
       [False,  True, False,  True, False, False, False, False,  True],
       [False,  True, False, False, False, False,  True, False,  True]], dtype=bool)
In [746]: np.where(np.all(_,axis=0))
Out[746]: (array([1, 8], dtype=int32),)

不能简单地使用np.where(假设这是找到元素的最佳方法),然后只检查满足第一个条件的模式。

import numpy as np
values = np.array([0,1,2,1,2,4,5,6,1,2,1])
searchval = [1,2]
N = len(searchval)
possibles = np.where(values == searchval[0])[0]

solns = []
for p in possibles:
    check = values[p:p+N]
    if np.all(check == searchval):
        solns.append(p)

print(solns)

我想这就是工作:

np.where((values == 1) & (np.roll(values,-1) == 2))[0]

相关问题 更多 >