Вы можете позволить 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 ()))
EDIT Таким образом, код сначала вычисляет изменение от каждой точки до следующей (gradient
). Следующий шаг немного сложен... Если вы сделаете np.diff((gradient > 0)
, результирующий логический массив будет True
, где есть изменение от растущего (> 0
) до нерастущего (<= 0
). Сделав его целым числом со знаком того же размера, что и логический массив, вы можете различать переходы от растущего к нерастущему (-1
) и обратному (+1
). Принимая .view(np.int8)
целочисленного типа со знаком того же размера dtype, что и логический массив, мы избегаем копирования данных, как это произошло бы, если бы мы сделали менее хакерский .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 раз.
person
Jaime
schedule
28.07.2013