6

Существует ли функция NumPy для возврата первого индекса элемента в массиве?

7

Я знаю, что в списках Python есть метод, который возвращает первый индекс элемента:

xs = [1, 2, 3]
xs.index(2)  # Вернет 1

Есть ли аналогичный метод для массивов NumPy?

5 ответ(ов)

0

Если вам нужен индекс первого вхождения только одного значения, вы можете использовать nonzero (или where, что в данном случае эквивалентно):

>>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8])
>>> nonzero(t == 8)
(array([6, 8, 9]),)
>>> nonzero(t == 8)[0][0]
6

Если вам нужно первое вхождение каждого из многих значений, вы, конечно, можете сделать то же самое многократно, но существует способ, который может быть быстрее. Следующий код находит индексы первого элемента каждой подпоследовательности:

>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)

Обратите внимание, что он находит начало как подпоследовательности из 3, так и обеих подпоследовательностей из 8:

[1, 1, 1, 2, 2, 3, 8, 3, 8, 8]

Таким образом, это немного отличается от нахождения первого вхождения каждого значения. В вашей программе вы можете работать с отсортированной версией t, чтобы получить желаемое:

>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
0

Вы также можете конвертировать массив NumPy в список и получить индекс элемента. Например:

l = [1, 2, 3, 4, 5]  # Список Python
a = numpy.array(l)    # Массив NumPy
i = a.tolist().index(2)  # i вернет индекс элемента 2
print(i)

Это выведет 1.

0

Если вы собираетесь использовать это в качестве индекса для чего-то другого, вы можете использовать булевы индексы, если массивы совместимы по размеру; вам не нужны явные индексы. Абсолютно самый простой способ сделать это - просто индексировать на основе логического значения.

other_array[first_array == item]

Любая булева операция работает:

a = numpy.arange(100)
other_array[first_array > 50]

Метод nonzero также принимает булевы массивы:

index = numpy.nonzero(first_array == item)[0][0]

Две нули используются для кортежа индексов (предполагая, что first_array одномерный), а затем мы берём первый элемент массива индексов.

0

Для одномерных массивов я бы рекомендовал использовать np.flatnonzero(array == value)[0]. Этот подход эквивалентен выражениям np.nonzero(array == value)[0][0] и np.where(array == value)[0][0], но позволяет избежать неаккуратности, связанной с распаковкой кортежа с одним элементом.

0

Чтобы проиндексировать по любым критериям, можно сделать что-то похожее на следующее:

In [1]: from numpy import *
In [2]: x = arange(125).reshape((5,5,5))
In [3]: y = indices(x.shape)
In [4]: locs = y[:,x >= 120] # замените x >= 120 на любые критерии
In [5]: pts = hsplit(locs, len(locs[0]))
In [6]: for pt in pts:
   .....:         print(', '.join(str(p[0]) for p in pt))
4, 4, 0
4, 4, 1
4, 4, 2
4, 4, 3
4, 4, 4

Также есть быстрая функция, которая делает то, что делает метод list.index(), только не вызывает исключение, если элемент не найден. Учтите, что это может быть очень медленно для больших массивов. Вы можете добавить это как метод для массивов, если хотите.

def ndindex(ndarray, item):
    if len(ndarray.shape) == 1:
        try:
            return [ndarray.tolist().index(item)]
        except:
            pass
    else:
        for i, subarray in enumerate(ndarray):
            try:
                return [i] + ndindex(subarray, item)
            except:
                pass

In [1]: ndindex(x, 103)
Out[1]: [4, 0, 3]

Надеюсь, это поможет!

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь