지난번 포스팅에서는

 

 - 다차원 배열 Indexing & Slicing

   ( 예: arr[0:2, 5:8] )

 - 다차원 배열 Boolean Indexing 

   ( 예: arr[bool_cond == 'A'] )

 

에 대해서 알아보았습니다.

 

이번 포스팅에서는 배열 Indexing의 세번째 방법으로서 정수 배열을 indexer로 사용해서 다차원 배열로 부터 Indexing하는 방법, Fancy Indexing에 대해 알아보겠습니다.  앞서의 배열 Indexing & Slicing 에서는 view 가 만들어졌었지만, Fancy Indexing은 copy를 만듭니다.

(세가지 방법이 서로 비슷비슷해서 뭐가 다른거지? 하는 혼란이 있을 것입니다.  이번 포스팅을 살펴본 후에 앞서의 2가지도 마저 비교해보면서 살펴볼 것을 권합니다)

 

Fancy Indexing의 경우 앞서 소개했었던 배열 Indexing 하는 부분에 '정수 배열(integer array)'이 들어갑니다.

 

(1) 특정 순서로 다차원 배열의 행을 Fancy Indexing 하기

(2) 특정 순서로 다차원 배열의 행과 열을 Fancy Indexing 하기 

 

로 나누어서 예를 들어 설명하겠습니다.

 

 

  (1) 특정 순서로 다차원 배열의 행(row)을 Fancy Indexing 하기

 

 

 

'axis 0' (row 기준)의 위에서 부터 아래 방향(from the first to the end)으로 '1'과 '2' 위치의 행(row) 전체를 fancy indexing 해보겠습니다. 대괄호(square brackets) 2개를 사용해서 a[[1, 2]] 처럼 입력해주면 됩니다.

 

 

In [1]: import numpy as np


In [2]: a = np.arange(15).reshape(5, 3)


In [3]: a

Out[3]:

array([[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11],
        [12, 13, 14]])

 

 

# (1) selecting a subset of the rows
# (1-1) selecting a subset of the rows by fancy indexing using integer arrays

In [4]: a[[1, 2]]

Out[4]:

array([[3, 4, 5],
        [6, 7, 8]])

 

 

 

 

'axis 0' (row 기준)의 아래에서 위 방향(from the end to the first) 으로 fancy indexing을 하고 싶으면 '-' (minus) 부호를 붙여주면 됩니다.  단, 이때는 indexing이 '0'부터 시작하는 것이 아니라 '1'부터 시작합니다. (헷갈리지요? -_-;)

 

 

# (1-2) selecting a subet of the rows from the end by using negative indices

 

In [5]: a[[-1, -2]]

Out[5]:

array([[12, 13, 14],
        [ 9, 10, 11]])

 

 

 

 

  (2) 특정 순서로 다차원 배열의 행(row)과 열(column)을 Fancy Indexing 하기

 

두가지 방법이 있습니다.

 

(2-1) 첫번째 방법은 (1-1)에서 소개했던 방법으로 특정 순서로 행(row)을 fancy indexing 합니다. 그런 후에 전체 행을 ':'로 선택하고, 특정 칼럼을 순서대로 배열을 사용해서 indexing을 한번 더 해주는 겁니다.

 

(2-2) 두번째 방법은 np.ix_ 함수를 사용해서 배열1 로 특정 행(row)을 지정, 배열2 로 특정 열(column)을 지정해주는 것입니다.

 

'0', '2', '4'의 행(row)을 indexing하고, '0', '2' 열(column)을 indexing 해오는 두가지 방법을 순서대로 예를 들어보겠습니다.

 

 

 

# (2) selecting a square region of the rows and columns
# (2-1) selecting subset by passing multiple index arrays first, and then selecting columns

 

In [6]: a[[0, 2, 4]][:, [0, 2]]

Out[6]:

array([[ 0,  2],
        [ 6,  8],
        [12, 14]])

 

 

# (2-2) by using np.ix_ function : converting two 1D integer arrays to an indexer

In [7]: a[np.ix_([0, 2, 4], [0, 2])]

Out[7]:

array([[ 0,  2],
        [ 6,  8],
        [12, 14]])

 

 

 

 

  (3) Fancy Indexing은 view가 아니라 copy 를 생성

 

다시 한번 강조하지만, Fancy Indexing 을 하게 되면 view가 아니라 copy 가 생성이 됩니다.  따라서 Fancy Indexing 후의 copy 된 배열에 변화를 주어도 원본 배열에는 아무런 영향이 없습니다.  (앞서의 포스팅에서 다루었던 배열 indexing & slicing에서는 거꾸로 copy가 아니라 view를 생성했었습니다. 그러다보니 view에 변화를 가하면 원본 배열에도 동일한 변화가 가해졌었습니다)

 

 

# (3) fancy indexing creates a copy, not a view

 

In [8]: a

Out[8]:

array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])


In [9]: a_copy = a[np.ix_([0, 2, 4], [0, 2])]


In [10]: a_copy

Out[10]:

array([[ 0,  2],
        [ 6,  8],
        [12, 14]])

 

 

# change to the copy of the ndarray

In [11]: a_copy[0, :] = 100


In [12]: a_copy

Out[12]:

array([[100, 100],
        [  6,   8],
        [ 12,  14]])

 

 

# no change to the original array

In [13]: a

Out[13]:

array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])

 

 

 

많은 도움 되었기를 바랍니다.

 

 

728x90
반응형
Posted by Rfriend
,