您可以让numpy处理迭代,即向量化它:
def local_maxima(xval, yval):
xval = np.asarray(xval)
yval = np.asarray(yval)
sort_idx = np.argsort(xval)
yval = yval[sort_idx]
gradient = np.diff(yval)
maxima = np.diff((gradient > 0).view(np.int8))
return np.concatenate((([0],) if gradient[0] < 0 else ()) +
(np.where(maxima == -1)[0] + 1,) +
(([len(yval)-1],) if gradient[-1] > 0 else ()))
编辑因此,代码首先计算从每个点到nex(gradient)的变化.下一步有点棘手…如果执行np.diff((gradient> 0),则结果布尔数组为True,其中从增长(> 0)变为不增长(< = 0)通过将其设置为与布尔数组相同大小的带符号的int,您可以区分从增长到不增长(-1)到相反的(1)的过渡.通过使用带符号的.view(np.int8)与boolean数组具有相同dtype大小的整数类型,我们避免复制数据,因为如果我们做些不太hacky .astype(int)会发生这种情况,剩下的工作就是照顾第一个和最后一个点,并连接所有点我今天发现的一件事是,如果在发送给np.concatenate的元组中包含一个空列表,它会以dtype np.float的空数组的形式出现,最终成为dtype结果,因此上述代码中的空元组的连接更加复杂.
有用:
In [2]: local_maxima(xval, yval)
Out[2]: array([ 1, 6, 10], dtype=int64)
并且相当快:
In [3]: xval = np.random.rand(10000)
In [4]: yval = np.random.rand(10000)
In [5]: local_maxima(xval, yval)
Out[5]: array([ 0, 2, 4, ..., 9991, 9995, 9998], dtype=int64)
In [6]: %timeit local_maxima(xval, yval)
1000 loops, best of 3: 1.16 ms per loop
另外,大多数时候都是将数据从列表转换为数组并对它们进行排序.如果您的数据已经排序并保存在数组中,则可以将上述性能提高5倍.