NumPy 배열에서 특정 행과 열 선택


98

나는 내가 여기서 어리석은 일을 잘못하고 있는지 파악하려고 미쳐 가고 있습니다.

저는 NumPy를 사용하고 있으며, 선택하려는 특정 행 인덱스와 특정 열 인덱스가 있습니다. 내 문제의 요지는 다음과 같습니다.

import numpy as np

a = np.arange(20).reshape((5,4))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19]])

# If I select certain rows, it works
print a[[0, 1, 3], :]
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [12, 13, 14, 15]])

# If I select certain rows and a single column, it works
print a[[0, 1, 3], 2]
# array([ 2,  6, 14])

# But if I select certain rows AND certain columns, it fails
print a[[0,1,3], [0,2]]
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# ValueError: shape mismatch: objects cannot be broadcast to a single shape

왜 이런 일이 발생합니까? 확실히 1, 2, 4 번째 행과 1, 3 번째 열을 선택할 수 있어야합니까? 내가 기대하는 결과는 다음과 같습니다.

a[[0,1,3], [0,2]] => [[0,  2],
                      [4,  6],
                      [12, 14]]

검색 가능성을 높이기 위해 태그가 지정된 numpy-slicing . (또한 '슬라이스'및 '슬라이싱'이라는 용어는 일반 텍스트에서 발생하지 않습니다.이 용어로 닫혀있는 일부 중복을 사용할 수 있습니다.)
smci

답변:


88

멋진 인덱싱을 사용하려면 각 차원에 대한 모든 인덱스를 제공해야합니다. 첫 번째 인덱스에는 3 개의 인덱스를 제공하고 두 번째 인덱스에는 2 개만 제공하므로 오류가 발생합니다. 다음과 같이하고 싶습니다.

>>> a[[[0, 0], [1, 1], [3, 3]], [[0,2], [0,2], [0, 2]]]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

물론 글을 쓰는 것은 고통스럽기 때문에 방송을 통해 다음과 같은 도움을받을 수 있습니다.

>>> a[[[0], [1], [3]], [0, 2]]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

목록이 아닌 배열로 인덱싱하면 훨씬 간단합니다.

>>> row_idx = np.array([0, 1, 3])
>>> col_idx = np.array([0, 2])
>>> a[row_idx[:, None], col_idx]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

4
감사합니다.이 작업을 할 수 있는지 몰랐습니다! 방송은 이상하고 훌륭합니다. 2 년 동안 멍청한 생활을했지만 여전히 익숙해지고 있습니다.
Praveen 2014

2
감사! 다른 답변은 선택한 행렬을 반환하는 측면에서 내 질문에 올바르게 대답했지만이 답변은 할당 문제도 해결하면서 문제를 해결했습니다 (a [[0,1,3], [0,2]] = 0을 설정하는 방법). 예).
Mike C

1
- @Jaime 그냥 어제 내가 정확히 방송 트릭을 수행하는 내장 - 당신이 제시 한 라이너를 발견 np.ix_
프라 빈

1
누군가 구문이 이와 같이 작동하는 이유에 대한 설명을 제공 할 수 있습니까? 첫 번째 예제에서는 작동하지만 세 번째 예제에서는 작동하지 않는 이유는 무엇입니까? 또한 원하는 인덱스를 자체 목록에 캡슐화하면이 문제를 어떻게 해결할 수 있습니까? 감사합니다
Aetos 2018 년

2
행은 중첩되어야하고 열은 그렇지 않은 이유는 무엇입니까?
AturSams

91

Toan이 제안했듯이 간단한 해킹은 먼저 행을 선택한 다음 그 위에 열을 선택하는 것 입니다 .

>>> a[[0,1,3], :]            # Returns the rows you want
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [12, 13, 14, 15]])
>>> a[[0,1,3], :][:, [0,2]]  # Selects the columns you want as well
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

[편집] 기본 제공 방법 : np.ix_

나는 최근에 numpy가 @Jaime이 제안한 것을 정확하게 수행 할 있도록 내장 된 단일 라이너를 제공 하지만 브로드 캐스팅 구문을 사용할 필요가 없다는 것을 발견했습니다 (가독성 부족으로 고통 받음). 문서에서 :

ix_ one을 사용하면 외적을 인덱싱 할 인덱스 배열을 빠르게 구성 할 수 있습니다. a[np.ix_([1,3],[2,5])]배열을 반환합니다 [[a[1,2] a[1,5]], [a[3,2] a[3,5]]].

따라서 다음과 같이 사용합니다.

>>> a = np.arange(20).reshape((5,4))
>>> a[np.ix_([0,1,3], [0,2])]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

작동 방식은 Jaime이 제안한 방식으로 배열을 정렬하여 브로드 캐스팅이 제대로 이루어 지도록하는 것입니다.

>>> np.ix_([0,1,3], [0,2])
(array([[0],
        [1],
        [3]]), array([[0, 2]]))

또한 MikeC가 의견에서 말했듯이 np.ix_첫 번째 (사전 편집) 답변은 그렇지 않은 뷰를 반환하는 이점이 있습니다. 즉, 이제 인덱스 배열에 할당 할 수 있습니다 .

>>> a[np.ix_([0,1,3], [0,2])] = -1
>>> a    
array([[-1,  1, -1,  3],
       [-1,  5, -1,  7],
       [ 8,  9, 10, 11],
       [-1, 13, -1, 15],
       [16, 17, 18, 19]])

4
몇 가지 테스트에서 np.ix_첫 번째 열을 선택한 다음 행을 선택하는 방법보다 빠르다 는 사실도 발견 했습니다 (일반적으로 모든 행과 열을 다시 인덱싱하는 1K-10K 크기의 정사각형 배열 테스트에서 약 2 배 빠름).
Nathan

7

사용하다:

 >>> a[[0,1,3]][:,[0,2]]
array([[ 0,  2],
   [ 4,  6],
   [12, 14]])

또는:

>>> a[[0,1,3],::2]
array([[ 0,  2],
   [ 4,  6],
   [12, 14]])

10
이것이 정확하지만 그것이 정확한지 설명하는 약간의 추가 정보를 게시하는 것을 고려해야 합니다.
ebarr 2014

2

사용하는 np.ix_것이 가장 편리한 방법이지만 (다른 사람이 대답 한대로) 여기에 또 다른 흥미로운 방법이 있습니다.

>>> rows = [0, 1, 3]
>>> cols = [0, 2]

>>> a[rows].T[cols].T

array([[ 0,  2],
       [ 4,  6],
       [12, 14]])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.