programing

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

kingscode 2022. 10. 29. 12:03
반응형

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

Python 리스트에서 첫 번째 인덱스를 반환하는 방법이 있다는 것을 알고 있습니다.

>>> xs = [1, 2, 3]
>>> xs.index(2)
1

NumPy 어레이에도 그런 게 있나요?

, 배열 시 " " " " " "array및값 , " " ",item검색할 수 있습니다.

itemindex = numpy.where(array == item)

결과는 먼저 모든 행 인덱스를 사용한 다음 모든 열 인덱스를 포함하는 튜플입니다.

예를 들어 어레이가 2차원이고 2개의 위치에 아이템이 포함되어 있는 경우

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

아이템과 같기 때문에 다음과 같습니다.

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

하나의 값만 처음 발생하는 인덱스가 필요한 경우 다음을 사용할 수 있습니다.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]),)

3s의 후속과 8s의 후속 양쪽의 선두가 되는 것에 주의해 주세요.

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

따라서 각 값의 첫 번째 항목을 찾는 것과는 약간 다릅니다.프로그램에서 정렬된 버전의 파일을 사용할 수 있습니다.t을 사용법

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

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이 인쇄됩니다.

첫 번째 인덱스를 검색하기 위해 를 기반으로 매우 성능이 뛰어나고 한 numba 대안을 추가하는 것 만으로는 다음과 같습니다.

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.where ★★★★★★★★★★★★★★★★★」np.nonzero.


단, 는 다차원 어레이를 적절하게 처리할 수도 있지만(수동으로 태플에 캐스팅해야 하며 단락되지 않아야 함) 일치하는 것이 발견되지 않으면 실패합니다.

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

l.index(x)i가 목록의 첫 번째 x 발생 인덱스 수 있도록 가장 작은 값으로 반환합니다.

…라고 할 수 .index()Python의 함수는 첫 번째 일치를 찾은 후 정지하도록 구현되어 있어 최적의 평균 성능을 얻을 수 있습니다.

NumPy 배열의 첫 번째 일치 후에 정지하는 요소를 찾으려면 반복기(ndenumate)를 사용합니다.

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)

NumPyNumPy)에는 다른 .argmax,where , , , , 입니다.nonzero배열 내의 요소를 찾는 데 사용할 수 있지만 모두 배열 전체를 통해 모든 항목을 찾아야 하므로 첫 번째 요소를 찾는 데 최적화되지 않습니다.또,where ★★★★★★★★★★★★★★★★★」nonzero어레이를 반환하기 때문에 인덱스를 가져올 첫 번째 요소를 선택해야 합니다.

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: 첫 번째 가치 지수를 빠르게 찾을 수 있습니다.

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

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라고 가정)에 대한 것이고 다음으로 인덱스 배열의 첫 번째 항목에 대한 것입니다.

1차원 정렬 배열의 경우 numpy를 사용하는 것이 훨씬 간단하고 효율적입니다.검색 정렬: NumPy 정수(위치)를 반환합니다.예를들면,

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

어레이가 이미 정렬되었는지 확인하세요.

또한 반환된 인덱스 i가 실제로 검색된 요소를 포함하는지 확인하십시오. 검색 정렬의 주요 목적은 순서를 유지하기 위해 요소를 삽입해야 하는 인덱스를 찾는 것입니다.

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

어레이는 1D를 np.flatnonzero(array == value)[0]np.nonzero(array == value)[0][0] ★★★★★★★★★★★★★★★★★」np.where(array == value)[0][0], 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 탭, 1개의 , 1개의 탭, 1

임의의 기준에 따라 인덱스를 작성하려면 다음과 같은 작업을 수행합니다.

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]

첫 번째 요소를 np에서 선택하는 대신 사용할 수 있습니다.여기서()은 다음과 같은 제너레이터 식을 열거와 함께 사용합니다.

>>> 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입니다.여기서 모든 요소가 일치하는지 확인합니다.배열의 초기에 일치하는 항목이 있으면 생성자 식이 더 빠릅니다.

NumPy에는 이를 달성하기 위해 조합할 수 있는 많은 작업이 있습니다.그러면 항목과 동일한 요소의 인덱스가 반환됩니다.

numpy.nonzero(array - item)

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

numpy_indexed 패키지(disclaimer, I am the author)에는 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로 일반화하며 결측값을 처리하는 다양한 방법이 있습니다.

8가지 방법의 비교

TL;DR:

(주의: 1억 요소 미만의 1D 어레이에 적용됩니다.)

  1. 최대한의 퍼포먼스 실현index_of__v5(numba+numpy.enumerate+forloop(아래 코드 참조)을 클릭합니다.
  2. 한다면numba사용할 수 없습니다.
    1. 사용하다index_of__v7(for루프 +enumerate타깃 값이 처음 100k 요소 내에서 발견될 것으로 예상되는 경우).
    2. 그렇지 않으면 사용index_of__v2/v3/v4(numpy.argmax또는numpy.flatnonzero베이스).

퍼포먼스 플롯

성능도에 의해 작동

import numpy as np
from numba import njit

# Based on: numpy.argmax()
# Proposed by: John Haberstroh (https://stackoverflow.com/a/67497472/7204581)
def index_of__v1(arr: np.array, v):
    is_v = (arr == v)
    return is_v.argmax() if is_v.any() else -1


# Based on: numpy.argmax()
def index_of__v2(arr: np.array, v):
    return (arr == v).argmax() if v in arr else -1


# Based on: numpy.flatnonzero()
# Proposed by: 1'' (https://stackoverflow.com/a/42049655/7204581)
def index_of__v3(arr: np.array, v):
    idxs = np.flatnonzero(arr == v)
    return idxs[0] if len(idxs) > 0 else -1


# Based on: numpy.argmax()
def index_of__v4(arr: np.array, v):
    return np.r_[False, (arr == v)].argmax() - 1


# Based on: numba, for loop
# Proposed by: MSeifert (https://stackoverflow.com/a/41578614/7204581)
@njit
def index_of__v5(arr: np.array, v):
    for idx, val in np.ndenumerate(arr):
        if val == v:
            return idx[0]
    return -1


# Based on: numpy.ndenumerate(), for loop
def index_of__v6(arr: np.array, v):
    return next((idx[0] for idx, val in np.ndenumerate(arr) if val == v), -1)


# Based on: enumerate(), for loop
# Proposed by: Noyer282 (https://stackoverflow.com/a/40426159/7204581)
def index_of__v7(arr: np.array, v):
    return next((idx for idx, val in enumerate(arr) if val == v), -1)


# Based on: list.index()
# Proposed by: Hima (https://stackoverflow.com/a/23994923/7204581)
def index_of__v8(arr: np.array, v):
    l = list(arr)
    try:
        return l.index(v)
    except ValueError:
        return -1

Colab으로 이동

이등분할모듈은이중분할모듈입니다.이중분할모듈은목록에서도동작하지만목록/배열을사전정렬해야합니다.

import bisect
import numpy as np
z = np.array([104,113,120,122,126,138])
bisect.bisect_left(z, 122)

수율

3

bisect는 찾고 있는 번호가 배열에 존재하지 않는 경우에도 결과를 반환하므로 올바른 위치에 번호를 삽입할 수 있습니다.

이것을 numpy에 내장된 꽤 관용적이고 벡터화된 방법이 있다.이를 위해 np.argmax() 함수의 쿼크를 사용합니다.많은 값이 일치하면 첫 번째 일치의 인덱스를 반환합니다.문제는 부울의 경우 두 가지 값만 존재한다는 것입니다.True (1) 및 False(0)따라서 반환되는 인덱스는 첫 번째 True의 인덱스가 됩니다.

여기에 기재되어 있는 간단한 예에서는, 다음과 같이 동작하고 있는 것을 확인할 수 있습니다.

>>> np.argmax(np.array([1,2,3]) == 2)
1

좋은 예로는 분류를 위한 버킷 계산 등이 있습니다.컷 포인트 배열이 있고 배열의 각 요소에 대응하는 "버킷"이 필요하다고 가정합니다.알고리즘은 첫 번째 지수를 계산하는 것입니다.cuts서 ''는x < cuts후)cutsnp.Infitnity후를 argmax에 할 수 cuts- 선 - 。

>>> cuts = np.array([10, 50, 100])
>>> cuts_pad = np.array([*cuts, np.Infinity])
>>> x   = np.array([7, 11, 80, 443])
>>> bins = np.argmax( x[:, np.newaxis] < cuts_pad[np.newaxis, :], axis = 1)
>>> print(bins)
[0, 1, 2, 3]

각 은 '''의 입니다.x는 잘 정의되고 지정이 용이한 에지 케이스 동작을 가진 순차 빈 중 하나에 속합니다.

참고: 이것은 python 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]

필터링된 요소의 첫 번째 인덱스를 가져옵니다.

python 3.6의 경우,

list(result)

대신

result

ndindex 사용

샘플 배열

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

...[[1,4],
    [2,3]]
 

인덱스와 요소 튜플을 저장할 빈 목록을 만듭니다.

 index_elements = []
 for i in np.ndindex(arr.shape):
     index_elements.append((arr[i],i))

 

튜플 리스트를 사전으로 변환하다

 index_elements = dict(index_elements)

키는 요소이고 값은 해당 인덱스입니다. 인덱스에 액세스하려면 키를 사용하십시오.

 index_elements[4] 
  
output
  ... (0,1)
  

사용 예에서는 요소의 순서가 중요하기 때문에 어레이를 미리 정렬할 수 없었습니다.다음은 All-NumPy 구현입니다.

import numpy as np

# The array in question
arr = np.array([1,2,1,2,1,5,5,3,5,9]) 

# Find all of the present values
vals=np.unique(arr)
# Make all indices up-to and including the desired index positive
cum_sum=np.cumsum(arr==vals.reshape(-1,1),axis=1)
# Add zeros to account for the n-1 shape of diff and the all-positive array of the first index
bl_mask=np.concatenate([np.zeros((cum_sum.shape[0],1)),cum_sum],axis=1)>=1
# The desired indices
idx=np.where(np.diff(bl_mask))[1]

# Show results
print(list(zip(vals,idx)))

>>> [(1, 0), (2, 1), (3, 7), (5, 5), (9, 9)]

중복된 값을 가진 정렬되지 않은 어레이를 설명하는 것 같습니다.

index_lst_form_numpy = pd.DataFrame(df).reset_index()["index"].tolist()

루프가 있는 다른 솔루션을 찾았습니다.

new_array_of_indicies = []

for i in range(len(some_array)):
  if some_array[i] == some_value:
    new_array_of_indicies.append(i)
    

언급URL : https://stackoverflow.com/questions/432112/is-there-a-numpy-function-to-return-the-first-index-of-something-in-an-array

반응형