배열에서 무언가의 첫 번째 인덱스를 반환하는 NumPy 함수가 있습니까?


답변:


522

예, 다음은 검색 할 NumPy 배열 array및 값에 대한 답변 item입니다.

itemindex = numpy.where(array==item)

결과는 먼저 모든 행 인덱스와 모든 열 인덱스가있는 튜플입니다.

예를 들어 배열이 2 차원이고 두 위치에 항목이 포함 된 경우

array[itemindex[0][0]][itemindex[1][0]]

당신의 품목과 같을 것입니다

array[itemindex[0][1]][itemindex[1][1]]

numpy.where


1
항목이 첫 번째 열에 존재하는 첫 번째 행을 찾고 있다면 이것이 작동합니다 (아무 것도 없으면 인덱스 오류가 발생하지만)rows, columns = np.where(array==item); first_idx = sorted([r for r, c in zip(rows, columns) if c == 0])[0]
BrT

27
첫 번째 값을 찾은 후 검색을 중지하려면 어떻게합니까? 내가 찾는 비교할 수) (여기서 생각하지 않는다 ()
마이클 Clerx

2
아! 당신이 성능에 관심이 있다면,이 질문에 대한 답을 체크 아웃 : stackoverflow.com/questions/7632963/...
마이클 Clerx

11
np.argwhere여기에 약간 더 유용 할 것입니다 :itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
Eric

3
이 답변은 배열이 2D라고 가정한다는 점은 주목할 가치가 있습니다. where모든 배열에서 작동하며 3D 배열 등에 사용될 때 길이 3의 튜플을 반환합니다.
P. Camilleri

69

하나의 value 만 처음 나타나는 색인이 필요한 경우 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]),)

4
무엇인지 설명해 주 r_시겠습니까?
Geoff

1
@Geoff는 r_연결합니다. 보다 정확하게는 슬라이스 객체를 각 축을 따라 연결로 변환합니다. hstack대신 사용할 수있었습니다 . 덜 혼란 스러웠을 수도 있습니다. 에 대한 자세한 내용은 설명서 를 참조하십시오 r_. 또한 있습니다 c_.
Vebjorn Ljosa

+1, 좋은 것! (vs. NP.where) 우리가 필요로하는 1D 배열에서 주어진 값이 처음으로 나타나는 경우 솔루션이 훨씬 간단하고 아마도 더 빠릅니다.
doug

3
후자의 경우 (모든 값의 첫 번째 인덱스를 찾는)vals, locs = np.unique(t, return_index=True)
askewchan

50

NumPy 배열을 변환하여 공중에 나열하고 색인을 얻을 수도 있습니다. 예를 들어

l = [1,2,3,4,5] # Python list
a = numpy.array(l) # NumPy array
i = a.tolist().index(2) # i will return index of 2
print i

1을 인쇄합니다.


처음 작성된 이후 라이브러리가 변경되었을 수 있습니다. 그러나 이것은 나를 위해 일한 첫 번째 솔루션이었습니다.
amracel

1
나는 목록 이해를 사용하여 목록에서 여러 값을 찾기 위해 이것을 잘 사용했습니다.[find_list.index(index_list[i]) for i in range(len(index_list))]
Matt Wenham

1
@MattWenham 충분히 큰 경우을 find_listNumPy 배열 object(또는 더 구체적인 것) 로 변환하고 할 수 있습니다 find_arr[index_list].
Narfanar

완전히 논외이지만, "공중에서"라는 구절을 처음으로 보게됩니다. 가장 많이 본 것은 아마도 "즉석에서"일 것입니다.
flow2k

18

성능이 뛰어나고 편리하게 추가하기 만하면됩니다. np.ndenumerate첫 번째 색인을 찾기위한 대안 :

from numba import njit
import numpy as np

@njit
def index(array, item):
    for idx, val in np.ndenumerate(array):
        if val == item:
            return idx
    # If no item was found return None, other return types might be a problem due to
    # numbas type inference.

이것은 매우 빠르며 다차원 배열을 자연스럽게 처리합니다 .

>>> arr1 = np.ones((100, 100, 100))
>>> arr1[2, 2, 2] = 2

>>> index(arr1, 2)
(2, 2, 2)

>>> arr2 = np.ones(20)
>>> arr2[5] = 2

>>> index(arr2, 2)
(5,)

이 될 수 있습니다 훨씬 더 빠르게 사용하는 방법보다 (이 때문에 작업을 단락) np.wherenp.nonzero.


그러나 np.argwhere또한 다룰 수있는 우아 (수동 조의 캐스팅에 당신이 필요 다차원 배열 하고 이 단락 아니에요)하지만 일치하는 항목이없는 경우는 실패합니다 :

>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)

2
@njit는 약식입니다. jit(nopython=True)즉, 함수가 첫 실행시 즉시 완전 컴파일되어 Python 인터프리터 호출이 완전히 제거됩니다.
bartolo-otrit

14

이 인덱스를 다른 인덱스로 사용하려는 경우 배열이 브로드 캐스팅 가능한 경우 부울 인덱스를 사용할 수 있습니다. 명시적인 지수가 필요하지 않습니다. 이를 수행하는 가장 간단한 방법은 진리 값을 기준으로 간단히 색인을 작성하는 것입니다.

other_array[first_array == item]

모든 부울 연산이 작동합니다.

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

0이 아닌 메소드도 부울을 사용합니다.

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

두 개의 0은 인덱스 튜플 (first_array가 1D라고 가정)에 대한 다음 인덱스 배열의 첫 번째 항목입니다.


10

l.index(x)최소 리턴 내가 되도록 리스트 X의 첫번째 발생의 인덱스이다.

index()파이썬 에서 함수가 구현되어 첫 번째 일치 항목을 찾은 후에 중지되도록 안전하게 가정 하여 최적의 평균 성능을 얻을 수 있습니다.

NumPy 배열에서 첫 번째 일치 후 중지되는 요소를 찾으려면 반복자 ( ndenumerate )를 사용하십시오.

In [67]: l=range(100)

In [68]: l.index(2)
Out[68]: 2

NumPy 배열 :

In [69]: a = np.arange(100)

In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)

두 방법 모두 참고 index()하고 next요소가 발견되지 않는 경우 오류를 반환합니다. 을 사용 next하면 요소를 찾을 수없는 경우 두 번째 인수를 사용하여 특수 값을 반환 할 수 있습니다.

In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)

NumPy ( argmax,, wherenonzero)에는 배열에서 요소를 찾는 데 사용할 수있는 다른 함수가 있지만 모든 배열을 통해 모든 항목을 찾는 단점이 있으므로 첫 번째 요소를 찾는 데 최적화되지 않습니다. 또한 주 wherenonzero인덱스를 얻을 수있는 첫 번째 요소를 선택해야하므로, 반환 배열.

In [71]: np.argmax(a==2)
Out[71]: 2

In [72]: np.where(a==2)
Out[72]: (array([2], dtype=int64),)

In [73]: np.nonzero(a==2)
Out[73]: (array([2], dtype=int64),)

시간 비교

검색된 항목이 배열의 시작 부분에있을 때 ( %timeitIPython 셸에서 사용) 큰 배열의 경우 반복자를 사용하는 솔루션이 더 빠릅니다 .

In [285]: a = np.arange(100000)

In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
100000 loops, best of 3: 17.6 µs per loop

In [287]: %timeit np.argmax(a==0)
1000 loops, best of 3: 254 µs per loop

In [288]: %timeit np.where(a==0)[0][0]
1000 loops, best of 3: 314 µs per loop

이것은 공개 NumPy GitHub 문제 입니다.

참고 : Numpy : 빠른 값의 첫 번째 색인 찾기


1
또한 최악의 경우 (마지막 요소)에 대한 타이밍을 포함해야 독자가 접근 방식을 사용할 때 최악의 경우에 발생하는 것을 알 수 있습니다.
MSeifert

@MSeifert 최악의 반복자 솔루션에 대한 합리적인 타이밍을 얻을 수 없습니다. 문제가 무엇인지 알 때까지이 답변을 삭제하겠습니다.
user2314737

1
작동하지 %timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))않습니까? 왜 1000 배 느린 지 궁금한 경우-numpy 배열에 대한 파이썬 루프가 악명 높기 때문입니다.
MSeifert

더 @MSeifert 내가 알고하지 않았다, 그러나 나는 또한 그 사실에 의아해 해요 argmax그리고 where이 경우에 훨씬 더 빠릅니다 (배열의 끝에 요소 검색)
user2314737

요소가 시작 부분에있는 것처럼 빠릅니다. 그들은 항상 전체 배열을 처리하므로 항상 같은 시간이 걸립니다 (적어도 그들은해야합니다).
MSeifert

9

1 차원 정렬 배열의 경우 NumPy 정수 (위치)를 반환하는 numpy.searchsorted 를 사용 하는 것이 훨씬 간단하고 효율적인 O (log (n) )입니다. 예를 들어

arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)

배열이 이미 정렬되어 있는지 확인하십시오.

또한 searchsorted의 주요 목표는 순서를 유지하기 위해 요소를 삽입 해야하는 인덱스를 찾는 것이므로 반환 된 인덱스 i에 실제로 검색 된 요소가 포함되어 있는지 확인하십시오.

if arr[i] == 3:
    print("present")
else:
    print("not present")

2
searchsorted는 검색하기 전에 배열을 정렬하지 않으므로 nlog (n)이 아닙니다. 인수 배열이 이미 정렬되어 있다고 가정합니다. numpy.searchsorted의 문서를 확인하십시오 (위 링크)
Alok Nayak

6

어떤 기준 으로든 색인을 작성하려면 다음과 같이 할 수 있습니다.

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] # put whatever you want in place of 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]

5

1D 배열의 경우을 권장합니다 np.flatnonzero(array == value)[0].이 둘 다 np.nonzero(array == value)[0][0]와 동일 np.where(array == value)[0][0]하지만 1 요소 튜플을 개봉하는 추악함을 피합니다.


4

np.where ()에서 첫 번째 요소를 선택하는 대안은 다음과 같이 열거 자와 함께 생성자 표현식을 사용하는 것입니다.

>>> import numpy as np
>>> x = np.arange(100)   # x = array([0, 1, 2, 3, ... 99])
>>> next(i for i, x_i in enumerate(x) if x_i == 2)
2

2 차원 배열의 경우 다음을 수행하십시오.

>>> x = np.arange(100).reshape(10,10)   # x = array([[0, 1, 2,... 9], [10,..19],])
>>> next((i,j) for i, x_i in enumerate(x) 
...            for j, x_ij in enumerate(x_i) if x_ij == 2)
(0, 2)

이 접근 방식의 장점은 첫 번째 일치 항목을 찾은 후 배열 요소 검사를 중지하는 반면 np.where는 모든 요소가 일치하는지 확인하는 것입니다. 배열의 초기에 일치하는 항목이 있으면 생성기 표현식이 더 빠릅니다.


배열에 일치하는 항목이 없을 경우이 방법을 사용하여 폴백 값을 편리하게 지정할 수도 있습니다. 첫 번째 예가 None폴백 으로 돌아 가면 이 next((i for i, x_i in enumerate(x) if x_i == 2), None)됩니다.
Erlend Magnus Viggen

4

NumPy에는이 작업을 수행하기 위해 함께 사용할 수있는 작업이 많이 있습니다. 항목과 동일한 요소의 인덱스를 반환합니다.

numpy.nonzero(array - item)

그런 다음 목록의 첫 번째 요소를 사용하여 단일 요소를 얻을 수 있습니다.


5
항목과 같지 않은 모든 요소의 인덱스를 제공 하지 않습니까?
Autoplectic

3

numpy_indexed 패키지 (부인, 나는 그것의 저자) numpy.ndarray에 대한 list.index의 벡터화 동등한를 포함 그건:

sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]
arrays_to_query = [[-5, 0], [1, 0]]

import numpy_indexed as npi
idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)
print(idx)   # [2, -1]

이 솔루션은 성능을 벡터화하고 ndarray로 일반화하며 결 측값을 처리하는 다양한 방법을 제공합니다.


-1

참고 : 이것은 파이썬 2.7 버전입니다

람다 함수를 사용하여 문제를 처리 할 수 ​​있으며 NumPy 배열과 목록 모두에서 작동합니다.

your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]

import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]

그리고 당신은 사용할 수 있습니다

result[0]

필터링 된 요소의 첫 번째 색인을 가져옵니다.

파이썬 3.6의 경우

list(result)

대신에

result

결과적 <filter object at 0x0000027535294D30>으로 Python 3 (Python 3.6.3에서 테스트)이 생성됩니다. 아마도 파이썬 3을 업데이트 하시겠습니까?
Peter Mortensen 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.