Numpy: быстро найти первый индекс стоимости - PullRequest
92 голосов
/ 03 октября 2011

Как найти индекс первого появления числа в массиве Numpy? Скорость важна для меня. Меня не интересуют следующие ответы, потому что они сканируют весь массив и не останавливаются, когда обнаруживают первое вхождение:

itemindex = numpy.where(array==item)[0][0]
nonzero(array == item)[0][0]

Примечание 1: ни один из ответов на этот вопрос не представляется актуальным Существует ли функция Numpy, которая возвращает первый индекс чего-либо в массиве?

Примечание 2: использование скомпилированного метода предпочтительнее цикла Python.

Ответы [ 14 ]

1 голос
/ 05 октября 2011

Насколько мне известно, только np.any и np.all в логических массивах закорочены.

В вашем случае numpy должен пройти весь массив дважды, один раз, чтобы создать логическое условиеи второй раз, чтобы найти индексы.

В этом случае я бы рекомендовал использовать Cython.Я думаю, что будет легко настроить пример для этого случая, особенно если вам не нужно много гибкости для разных типов и форм.

0 голосов
/ 01 апреля 2016

как насчет этого

import numpy as np
np.amin(np.where(array==item))
0 голосов
/ 07 марта 2014

Просто обратите внимание, что если вы выполняете последовательность поисков, выигрыш в производительности от выполнения чего-то умного, такого как преобразование в строку, может быть потерян во внешнем цикле, если измерение поиска недостаточно велико.Посмотрите, как производительность итерации find1, которая использует предложенный выше трюк преобразования строк, и find2, которая использует argmax вдоль внутренней оси (плюс корректировка для обеспечения того, что несоответствие возвращает как -1)

import numpy,time
def find1(arr,value):
    return (arr==value).tostring().find('\x01')

def find2(arr,value): #find value over inner most axis, and return array of indices to the match
    b = arr==value
    return b.argmax(axis=-1) - ~(b.any())


for size in [(1,100000000),(10000,10000),(1000000,100),(10000000,10)]:
    print(size)
    values = numpy.random.choice([0,0,0,0,0,0,0,1],size=size)
    v = values>0

    t=time.time()
    numpy.apply_along_axis(find1,-1,v,1)
    print('find1',time.time()-t)

    t=time.time()
    find2(v,1)
    print('find2',time.time()-t)

output

(1, 100000000)
('find1', 0.25300002098083496)
('find2', 0.2780001163482666)
(10000, 10000)
('find1', 0.46200013160705566)
('find2', 0.27300000190734863)
(1000000, 100)
('find1', 20.98099994659424)
('find2', 0.3040001392364502)
(10000000, 10)
('find1', 206.7590000629425)
('find2', 0.4830000400543213)

Тем не менее, находка, написанная на C, будет, по крайней мере, немного быстрее, чем любой из этих подходов

0 голосов
/ 23 октября 2012

Вы можете преобразовать свой массив в list и использовать его index() метод:

i = list(array).index(item)

Насколько я знаю, это скомпилированный метод языка Си.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...