4.4.5 2차원 배열의 색인

[비유로 이해하기: 아파트 호수 찾기] 엑셀 시트나 행렬에서 특정 값을 가져오려면 행(Row)열(Column)의 좌표가 정확히 필요합니다. [행, 열] 좌표를 지정하여 원소 값을 콕 집어 가져올 수 있습니다. -1 인덱스를 활용하면 “맨 마지막(펜트하우스)”부터 역순으로 탐색할 수 있어 직관적입니다. 또한 리스트로 원하는 인덱스를 이빨 빠진 듯 불연속적으로 선택하는 방식을 ‘팬시 인덱싱(Fancy Indexing)’이라고 부르며, 추천 시스템처럼 유저가 좋아하는 상품 번호만 쏙쏙 골라 담을 때 막강한 힘을 발휘합니다.

다음 모양 (7, 8)의 2차원 배열 x가 있다.

from numpy import arange

x = arange(56).reshape(7, 8)
x

출력:

array([[ 0,  1,  2,  3,  4,  5,  6,  7],
       [ 8,  9, 10, 11, 12, 13, 14, 15],
       [16, 17, 18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29, 30, 31],
       [32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47],
       [48, 49, 50, 51, 52, 53, 54, 55]])

이미 배운 첨자 색인이나 슬라이싱은 고급 인덱싱과 다르다. 다음은 일반 색인 방법이다.

x[0, 1]

출력:

1

다음은 일반 슬라이싱 방법이다. 다음으로 모든 행(:)의 첨자 2열부터 7열(2:8)로 구성된 모양 (7, 6)의 2차원 배열이 반환된다.

x[:, 2:8]

출력:

array([[ 2,  3,  4,  5,  6,  7],
       [10, 11, 12, 13, 14, 15],
       [18, 19, 20, 21, 22, 23],
       [26, 27, 28, 29, 30, 31],
       [34, 35, 36, 37, 38, 39],
       [42, 43, 44, 45, 46, 47],
       [50, 51, 52, 53, 54, 55]])

다음은 간단한 고급 색인 방법으로 0축과 1축에 각각 목록이 기술된다. 결과는 첨자에 해당하는 값이다.

x[[0], [1]]

출력:

array([1])

다음으로 모든 행의 5열과 4열로 구성된 모양 (7, 2)의 2차원 배열이 반환된다.

x[:, [5, 4]]

출력:

array([[ 5,  4],
       [13, 12],
       [21, 20],
       [29, 28],
       [37, 36],
       [45, 44],
       [53, 52]])

다음으로 1행과 3행의 모든 열로 구성된 모양 (2, 8)의 2차원 배열이 반환된다.

x[[1, 3]]

출력:

array([[ 8,  9, 10, 11, 12, 13, 14, 15],
       [24, 25, 26, 27, 28, 29, 30, 31]])

다음은 위 구문과 같으며 1행과 3행의 모든 열로 구성된 모양 (2, 8)의 2차원 배열이 반환된다.

x[[1, 3], :]

출력:

array([[ 8,  9, 10, 11, 12, 13, 14, 15],
       [24, 25, 26, 27, 28, 29, 30, 31]])

다음처럼 0축과 1축의 배열의 수가 같으면 각각 대응되는 순서대로 첨자 [1, 2][3, 2]에 해당하는 10과 26으로 구성된 모양 (2, )의 1차원 배열이 반환된다.

x[[1, 3], [2, 2]]

출력:

array([10, 26])

다음처럼 0축과 1축의 배열의 수가 같지 않으면, [2]가 브로드캐스팅이 수행되어 [2, 2]가 되어 각각 대응되는 순서대로 첨자 [1, 2][3, 2]에 해당하는 10과 26으로 구성된 모양 (2, )의 1차원 배열이 반환된다. 결국, 위와 같다.

x[[1, 3], [2]]

출력:

array([10, 26])

다음도 0축과 1축의 배열의 수가 같으므로 각각 대응되는 순서대로 첨자 [1, 3][3, 3]에 해당하는 11과 27로 구성된 모양 (2, )의 1차원 배열이 반환된다.

x[[1, 3], [3, 3]]

출력:

array([11, 27])

다음 코드는 [3]이 브로드캐스팅이 수행되어 [3, 3]이 되어 각각 대응되는 순서대로 첨자 [1, 3][3, 3]에 해당하는 11(=x[1, 3])과 27(=x[3, 3])로 구성된 모양 (2, )의 1차원 배열이 반환된다. 결국, 위와 같다.

x[[1, 3], [3]]

출력:

array([11, 27])

다음처럼 브로드캐스팅이 될 수 없는 형태인 모양 (3, )과 모양 (2, )이면 오류가 발생한다.

from numpy import array
x[array([0, 2, 4]), array([0, 1])]

오류:

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)

다음 코드는 이미 알아보았듯이 1축의 1이 브로드캐스팅이 수행되어 [1, 1, 1]이 되어 각각 대응되는 순서대로 첨자 [0, 1][2, 1], [4, 1]에 해당하는 [1, 17, 33]으로 구성된 모양 (3, )의 1차원 배열이 반환된다.

x[np.array([0, 2, 4]), 1]

출력:

array([ 1, 17, 33])

결과는 x[0, 1], x[2, 1], x[4, 1]의 참조 값으로 구성된 1차원 배열이 된다.

print(x[0, 1])
print(x[2, 1])
print(x[4, 1])

출력:

1
17
33
서브목차