이번 포스팅부터는 몇 번에 나누어서 로그함수, 삼각함수, 사칙연산 함수 등과 같이 일반적으로 많이 사용되는 범용 함수 (universal functions)들에 대해서 소개하겠습니다.

 

Python에서 범용 함수를 지원하는 모듈이 여러개 있습니다. 

 

Pytho 배울 때 초반에 배우는 math module은 실수(real number)에 대해서만 범용함수를 지원하며, cmath module 은 복소수(complex number) 까지 범용함수를 지원합니다. numpy module은 실수, 복소수, 복소수 행렬 (complex matrix)의 원소 간 범용 함수를 모두 지원하므로 사용 범위가 가장 넓어 매우 유용합니다.  배열의 원소간 연산을 위해 NumPy의 Ufunc 함수는 쓸모가 많습니다. NumPy는 맥가이버 칼 같다고나 할까요.

 

[ Python modules for Universal Functions ]

 

 

 

 

NumPy 범용 함수는 몇 개의 배열에 대해 적용이 되는지에 따라서

 - (1) 1개의 배열에 적용하는 Unary Universal Functions (ufuncs)

 - (2) 2개의 배열에 대해 적용하는 Binary Universal Functions (ufuncs)

으로 구분할 수 있습니다.

 

범용함수 종류가 너무 많아서 포스팅에 한꺼번에 소개하기가 버거우므로, 서너번에 나누어서 Unary Universal Functions를 먼저 소개하고, 다음으로 Binary Ufuncs  순서로 알아보겠습니다.

 

 

 

 

  (1-1) 올림 혹은 내림 범용 함수 (round universal functions)

 

비슷비슷한 함수들이 여러개 있는데요, 말로 설명하는 것보다 예를 자세히 살펴보고 비교해보는 것이 이해하기에 쉽고 빠를 것 같습니다.

 

 

# import module and making an array

In [1]: import numpy as np


In [2]: a = np.array([-4.62, -2.19, 0, 1.57, 3.40, 4.06])


In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

 

 

 (1-1-1) np.around(a) : 0.5를 기준으로 올림 혹은 내림

 

 

# np.around(a) : Evenly round to the given number of decimals

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [4]: np.around(a)

Out[4]: array([-5., -2., 0., 2., 3., 4.]) 

 

 

 

 

 (1-1-2) np.round_(a, N) : N 소수점 자릿수까지 반올림

 

  

# np.round_(a, n) : Round an array to the given number of decimals

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [5]: np.round_(a, 1)

Out[5]: array([-4.6, -2.2, 0. , 1.6, 3.4, 4.1]) 

 

 

 

 

 (1-1-3) np.rint(a) : 가장 가까운 정수로 올림 혹은 내림

 

 

# round elements to the nearest integer

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [6]: np.rint(a)

Out[6]: array([-5., -2., 0., 2., 3., 4.])

 

 

 

 

 (1-1-4) np.fix(a) : '0' 방향으로 가장 가까운 정수로 올림 혹은 내림

 

 

# Round to nearest integer towards zero

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [7]: np.fix(a)

Out[7]: array([-4., -2., 0., 1., 3., 4.])

 

 

 

 

 (1-1-5) np.ceil(a) : 각 원소 값보다 크거나 같은 가장 작은 정수 값 (천장 값)으로 올림

 

 

# the smallest integer greater than or equal to each element 

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [8]: np.ceil(a)

Out[8]: array([-4., -2., 0., 2., 4., 5.])

 

 

 

 

 (1-1-6) np.floor(a) : 각 원소 값보다 작거나 같은 가장 큰 정수 값 (바닥 값)으로 내림

 

 

# the largest integer less than or equal to each element

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [9]: np.floor(a)

Out[9]: array([-5., -3., 0., 1., 3., 4.])

 

 

 

 

 (1-1-7) np.trunc(a) : 각 원소의 소수점 부분은 잘라버리고 정수값만 남김

 

 

# Return the truncated value of the input, element-wise

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [10]: np.trunc(a)

Out[10]: array([-4., -2., 0., 1., 3., 4.])

 

 

 

다음번 포스팅에서는 단일 배열 범용 함수의 두번째 순서로 합(sums), 곱(products), 차분(difference), 미분(gradient) 함수에 대해서 알아보도록 하겠습니다.

 

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

 

 

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by R Friend R_Friend

지난번 포스팅에서는

 

 - 다차원 배열 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]])

 

 

 

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

 

 

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by R Friend R_Friend

지난번 포스팅에서 Python NumPy의 배열 Indexing & Slicing 에 대해서 소개를 했었습니다.

 

이번 포스팅에서는 배열 Indexing & Slicing 에 조금 더 살을 붙여볼 텐데요, 조건문을 가지고 True, False 로 Indexing을 해보는 "Boolean Indexing" 입니다. 

 

데이터 전처리를 하다보면 == (equal), != (not equal), & (and), | (or) 등의 조건문 연산자를 활용해서 indexing & slicing 해야할 때가 종종 있으므로 이번 포스팅도 씀씀이가 솔솔할겁니다.

 

 

 

 

 

2차원 배열을 가지고 간단한 예를 들어서 설명해보겠습니다.

 

  (1) 특정 조건을 만족하는 배열의 모든 열을 선별하기 : ==

 

 

# making a 2D array

 

In [1]: import numpy as np


In [2]: arr = np.arange(20).reshape(5, 4)


In [3]: arr

Out[3]:

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

 

 

 

 

Boolean 조건값으로 사용할 배열을 하나 만들어 보겠습니다. 

 

Boolean Indexing 할 때 원래 배열의 축(axis 0) 의 원소 개수가 Boolean 배열의 원소의 개수와 같아야 합니다.  이번 예에서는 arr 배열의 shape 이 (5, 4) 이므로 행(row)의 '5'에 맞추어서 '5'개의 원소(element)로 구성된 'axis_ABC'라는 배열을 만들었습니다.

 

 

# an array of 'axis_ABC' with duplicates

 

In [4]: axis_ABC = np.array(['A', 'A', 'B', 'C', 'C'])

In [5]: axis_ABC

Out[5]:

array(['A', 'A', 'B', 'C', 'C'],
        dtype='<U1')

 

 

 

 

axis_ABC == 'A' 인 행 전체를 배열 'arr'로 부터 indexing 해보겠습니다.  전체 열을 같이 indexing 해오라고 지시하기 위해 콤마(comma) ','와 콜론 (colon) ':' 을 사용해도 되고, 생략해도 됩니다.

 

 

# selecting all the rows which axis_ABC equals(==) 'A'

 

In [6]: axis_ABC == 'A'

Out[6]: array([ True, True, False, False, False], dtype=bool)


In [7]: arr[axis_ABC == 'A']

Out[7]:

array([[0, 1, 2, 3],
        [4, 5, 6, 7]])

 

 

# the same result with the above

In [8]: arr[axis_ABC == 'A', :]

Out[8]:

array([[0, 1, 2, 3],
        [4, 5, 6, 7]])

 

 

 

 

옆길로 조금 빠져보자면요, Boolean 조건으로 행(row) 전체를 indexing 하고, 콤마(comma) ','  와 함께 콜론(colon) ':'으로 slicing을 하거나 정수(integer)로 열(column)을 indexing 하는 예를 들어보겠습니다.

 

 

# slicing with colon ':'

 

In [9]: arr[axis_ABC == 'A', :2]

Out[9]:

array([[0, 1],
        [4, 5]])

 

 

# indexing with interger => result to low dimension array

In [10]: arr[axis_ABC == 'A', 2]

Out[10]: array([2, 6])

 

 

 

 

 

  (2) 특정 조건을 만족하지 않는 배열의 모든 열을 선별하기 : !=, ~(==)

 

위의 예와는 정반대로 'A'가 아닌 전체 열(row)을 indexing 해보겠습니다. 

'!='와 '~(==)'의 두가지 방법이 있습니다.

 

 

In [3]: arr

Out[3]:

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

 

In [4]: axis_ABC = np.array(['A', 'A', 'B', 'C', 'C'])

 

 

# selecting all the rows except 'A' : != 'A'

 

In [11]: arr[axis_ABC != 'A']

Out[11]:

array([[ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [16, 17, 18, 19]])

 

 

# selecting all the rows except 'A' : ~(axisABC == 'A')

In [12]: arr[~(axis_ABC == 'A')]

Out[12]:

array([[ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [16, 17, 18, 19]])

 

 

 

 

 

  (3) 복수의 조건으로 배열의 특정 열 선별하기 : & (and), | (or)

 

Boolean 조건문으로 두 개 이상의 복수개를 사용할 때가 있겠지요?  & (and), | (or) operator로 복수의 조건문을 엮어서 indexing 하는 예를 들어보겠습니다.

 

 

In [3]: arr

Out[3]:

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

 

In [4]: axis_ABC = np.array(['A', 'A', 'B', 'C', 'C'])

 

 

# indexing by using mutiple boolean conditions, & (and), | (or)

 

In [13]: arr[(axis_ABC == 'A') | (axis_ABC == 'B')]

Out[13]:

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


In [14]: arr[(axis_ABC != 'A') & (axis_ABC != 'B')]

Out[14]:

array([[12, 13, 14, 15],
        [16, 17, 18, 19]])

 

 

 

 

이때 유의할 게 있는데요, '&', '|' 대신에 'and' 혹은 'or' syntax로 직접 입력하면 'ValueError' 메시지가 뜹니다.

 

 

# ValueError : and, or syntax

 

In [15]: arr[(axis_ABC != 'A') and (axis_ABC != 'B')]

Traceback (most recent call last):


File "<ipython-input-15-ca8b3629eb98>", line 1, in <module>

arr[(axis_ABC != 'A') and (axis_ABC != 'B')]


ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

 

 

 

 

 

  (4) Booean 조건에 해당하는 배열 Indexing에 스칼라 값을 할당하기

 

 

In [3]: arr

Out[3]:

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

 

In [4]: axis_ABC = np.array(['A', 'A', 'B', 'C', 'C'])

 

 

# assigning salcar values with boolean arrays

 

In [16]: arr[axis_ABC == 'A'] = 100


In [17]: arr

Out[17]:

array([[100, 100, 100, 100],
        [100, 100, 100, 100],
        [  8,   9,  10,  11],
        [ 12,  13,  14,  15],
        [ 16,  17,  18,  19]])


 

In [18]: arr[arr >= 100] = 0


In [19]: arr

Out[19]:

array([[ 0,  0,  0,  0],
        [ 0,  0,  0,  0],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [16, 17, 18, 19]])

 

 

In [20]: arr[(arr >= 8) & (arr <= 15)] = 10


In [21]: arr

Out[21]:

array([[ 0,  0,  0,  0],
        [ 0,  0,  0,  0],
        [10, 10, 10, 10],
        [10, 10, 10, 10],
        [16, 17, 18, 19]])

 

 

 

다음번 포스팅에서는 특정 순서로 행과 열을 선택하는 Fancy Indexing 에 대해서 알아보겠습니다.

 

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

 

 

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by R Friend R_Friend

예전에 Python Pandas 의 DataFrame 전처리에 대해서 연재할 때 DataFrame의 행 또는 열 데이터 선택해서 가져오기 (Indexing and selection of DataFrame objects) 하는 방법에 대해서 소개했던 적이 있습니다.

 

이번 포스팅에서는 Python NumPy 배열의 일부분, 부분집합을 선택 (Indexing and slicing an ndarray) 하는 방법을 알아보겠습니다.  

 

다차원 배열 다룰 때 indexing, slicing 은 마치 밥 먹을 때 수시로 김치에 젖가락이 가듯이 그냥 일상적으로 사용하곤 하므로 정확하게 알아둘 필요가 있습니다.

 

1차원 배열, 2차원 배열, 3차원 배열의 순서대로 indexing 하는 방법을 간단한 예를 들어서 설명해보겠습니다.

 

 

 

 

  (1-1) Indexing a subset of 1D array : a[from : to]

 

 

#%% NumPy array Indexing and Slicing

 

In [1]: import numpy as np


In [2]: a = np.arange(10)


In [3]: a

Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

 

 

# (1-1) Indexing a subset of 1D array

In [4]: a[0]

Out[4]: 0

In [5]: a[0:5]

Out[5]: array([0, 1, 2, 3, 4])

 

 

 

 

  (1-2) array slices are views of the original array and are not a copy

 

Python NumPy의 배열 indexing, slicing에서 유의해야할 것이 있습니다.  배열을 indexing 해서 얻은 객체는 복사(copy)가 된 독립된 객체가 아니며, 단지 원래 배열의 view 일 뿐이라는 점입니다.  따라서 view를 새로운 값으로 변경시키면 원래의 배열의 값도 변경이 됩니다.

 

아래 예에서 원래의 배열 'b'의 0, 1, 2 위치의 원소에 빨간색으로 밑줄을 그어놨습니다.  배열 b에서 0, 1, 2, 3, 4 위치의 값을 indexing 해서 만든 b_idx 배열은 원래 배열 b의 view 일 뿐이며, copy가 아닙니다. b_idx 에서 뭔가 변화가 일어나면 원래의 배열 b에도 b_idx의 변화가 반영됩니다.  b_idx의 0, 1, 2 위치의 원소 값을 '10'으로 바꿔치기 했더니 원래의 배열 b의 0, 1, 2 위치의 값도 '10'으로 바뀌어있음을 알 수 있습니다.

 

 

In [6]: b = np.arange(10)


In [7]: b

Out[7]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])


In [8]: b_idx = b[0:5]


In [9]: b_idx

Out[9]: array([0, 1, 2, 3, 4])

 

 

# Assigning(Broadcasting) a scalar to a slice of 1D array

In [10]: b_idx[0:3] = 10


In [11]: b_idx

Out[11]: array([10, 10, 10, 3, 4])

 

 

# compare this 'b' with the original array 'b' above, it's different!!!

In [12]: b

Out[12]: array([10, 10, 10, 3, 4, 5, 6, 7, 8, 9])

 

 

 

R 사용자라면 위 상황을 보고 아주 당황스러울 것입니다.  R에서는 indexing을 하면 무조건 copy 가 되고, 원래의 배열과 indexing한 후의 배열은 전혀 별개의, 독립된 객체로 간주가 되거든요.  그래서 저 같은 경우는 크기가 매우 큰 배열의 경우 아주 작은 일부분만 indexing을 해 온후에, 작은 크기의 indexing한 배열을 가지고 데이터 조작 test를 이렇게 저렇게 다양하게 해 본 후에, 제대로 작동하는 걸 확인한 최종 R script를 원래의 크기가 큰 배열에 적용하곤 했거든요.  indexing 했던 배열에 제가 무슨 짓을 하던 그건 원래의 배열에 영향이 없었던 거지요.

 

반면에, Python NumPy의 배열에서는 indexing해온 배열에 제가 무슨 짓을 하면요, 그게 원래의 배열에도 반영이 되는 줄을 처음에 몰랐었습니다. 그러다 보니 indexing했던 배열에 이런, 저런 test 해보고 나서 원래 배열이 변질(?)이 된 것 보고 '이게 뭐지?  왜 이런 거지?  무슨 일이 벌어진 거지?  이거 혹시 버그?'... 뭐, 이랬습니다.  한참을 이랬습니다.  에휴... -_-;

 

Python NumPy가 배열 indexing 할 때 copy가 view를 반환하는데는 이유가 있겠지요?  그건 성능(performance)을 높이고 메모리(memory) 이슈를 피하기 위해서 입니다.

 

 

 

  (1-3) indexing한 배열을 복사하기 : arr[0:5].copy()

 

배열을 indexing 한 후에 얻은 배열을 복사하고 싶으면, 그래서 원래의 배열과 독립된 배열로 처리하고 싶으면 copy() method 를 사용하면 됩니다.  아래 예는 c[0:5].copy() 만 다르고, 나머지는 위의 예와 동일한데요, 제일 마지막의 [19] 번 결과를 보면 원래의 배열 'c'가 indexing된 배열 'c_idx_copy'가 중간에 바뀐것에 영향을 안받고 원래의 값을 그대로 유지하고 있습니다.  빨간색으로 밑줄 그어놓은 부분을 위의 [12]번 결과와 아래의 [19]번 결과를 비교해보시기 바랍니다.

 

 

In [13]: c = np.arange(10)


In [14]: c

Out[14]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])


In [15]: c_idx_copy = c[0:5].copy()


In [16]: c_idx_copy

Out[16]: array([0, 1, 2, 3, 4])


In [17]: c_idx_copy[0:3] = 10


In [18]: c_idx_copy

Out[18]: array([10, 10, 10, 3, 4])


In [19]: c

Out[19]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

 

 

 

 

이제 2차원 배열로 넘어가 볼까요?

 

  (2-1) Indexing and Slicing 2D array with comma ',' : d[0:3, 1:3]

 

행과 열 기준으로 위치를 지정해주어서 indexing을 하며, 연속된 위치 값의 경우 '0:2' 처럼 콜론(colon) ':' 를 사용하면 편리합니다. 행과 열의 구분은 콤마(comma) ',' 를 사용합니다.

 

아래 몇 가지 유형별로 예시를 들어놓았으니 indexing 방법과 결과를 살펴보시기 바랍니다.

 

 

In [20]: d = np.arange(20).reshape(4, 5)


In [21]: d

Out[21]:

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

 

 

# indexing a row of 2D array => returning a 1D array

In [22]: d[0]

Out[22]: array([0, 1, 2, 3, 4])

 

 

# indexing mutiple rows in a row of 2D array : use colon ':'

 

In [23]: d[0:2]

Out[23]:

array([[0, 1, 2, 3, 4],
        [5, 6, 7, 8, 9]])

 

 

# indexing an element of of 2D array : use comma ','

 

In [24]: d[0, 4]

Out[24]: 4

 

In [25]: d[0:3, 1:3]

Out[25]:

array([[ 1,  2],
        [ 6,  7],
        [11, 12]])

 

 

 

 

  (2-2) Indexing and Slicing 2D array with square bracket '[ ][ ]' : d[0:3][1:3]

 

NumPy 배열을 행과 열을 기준으로 indexing 할 때 콤마(comma) ','를 사용하지 않고 아래 처럼 대괄호(square bracket)을 두개 '[ ][ ]' 처럼 사용할 수도 있습니다. 다만, indexing 하는 순서와 결과가 위에서 예를 들었던 콤마 ','를 사용하는 것과 조금 다르므로 주의하기 바랍니다.

 

대괄호 두개 '[ ][ ]'는 첫번째 대괄호 '[ ]'에서 indexing을 먼저 하고 나서, 그 결과를 가져다가 두번째 대괄호 '[ ]'에서 한번 더 indexing을 하게 됩니다. 

 

 

In [26]: d

Out[26]:

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


In [27]: d[0][4] # the same result with the above [24]

Out[27]: 4


In [28]: d[0:3][1:3] # a different result from the above [25], working sequencially

Out[28]:

array([[ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14]])

 

 

 

 

  (2-3) array slices are views of the original array and are not a copy

 

위의 (1-2) 에서 NumPy 배열을 indexing해서 얻은 배열은 원래 배열의 copy가 아니라 view 라고 했었습니다.  2차원 배열도 똑같습니다.  복습하는 차원에서 2차원 배열에서 indexing한 view 'd_idx_0'에 일부 변화를 줘보겠습니다.  그랬더니 원래 배열 'd'에도 view 'd_dix_0'의 변화가 반영이 되었음을 알 수 있습니다.

 

 

# assigning a scalar value to the subset(1D array) of 2D array

 

In [29]: d

Out[29]:

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


In [30]: d_idx_0 = d[0]


In [31]: d_idx_0

Out[31]: array([0, 1, 2, 3, 4])


In [32]: d_idx_0[0:2] = 100


In [33]: d_idx_0

Out[33]: array([100, 100, 2, 3, 4])

 

 

# once again, subset of array by indexing is not a copy, but a view!!!

In [34]: d

Out[34]:

array([[100, 100,   2,   3,   4],
        [  5,   6,   7,   8,   9],
        [ 10,  11,  12,  13,  14],
        [ 15,  16,  17,  18,  19]])

 

 

 

 

3차원 배열 indexing도 마저 알아보겠습니다. 

 

  (3-1) Indexing and Slicing of 3D array : e[0, 0, 0:3]

 

방법은 위의 1차원 배열, 2차원 배열 indexing과 동일합니다.  3차원이 되면 2차원 배열이 층을 이루어서 겹겹이 쌓여서 나타나게 되어서 좀 헷갈릴 수 있는데요, 아래에 몇 개 indexing 유형별로 예를 들었으니 참고하시기 바랍니다.

 

층을 먼저 선택(2차원 배열 덩어리 중에서 먼저 indexing) 하는 것이 추가가 된 것이구요, 그 다음의 indexing은 위의 2차원 배열 indexing 방법과 동일합니다.

 

 

# (3-1) Indexing and Slicing 3D array

 

In [35]: e = np.arange(24).reshape(2, 3, 4)


In [36]: e

Out[36]:

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]]])

 

 

# indexing the first array with shape(3, 4) from the 3D array with shape(2, 3, 4)

In [37]: e_idx_0 = e[0]


In [38]: e_idx_0

Out[38]:

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

 

 

# indexing the first row of the first array with shape(3, 4) from the 3D array with shape(2, 3, 4)

In [39]: e_idx_0_0 = e[0, 0]


In [40]: e_idx_0_0

Out[40]: array([0, 1, 2, 3])

 

 

# indexing the '0, 1, 2' elements from the first row of the first array with shape(3, 4)

# from the 3D array with shape(2, 3, 4)

In [41]: e_idx_0_0_0_2 = e[0, 0, 0:3]


In [42]: e_idx_0_0_0_2

Out[42]: array([0, 1, 2])

 

 

 

 

  (3-2) 축 하나를 통째로 가져오기( indexing the entire axis by using colon ':')

 

콜론(colon) ':' 을 사용해서 행 축(row, axis 0)을 통째로 slicing 해올 수 있습니다.

 

 

In [44]: e

Out[44]:

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]]])

 

 

# indexing the entire axis by using colon ':'

 

In [43]: e[0, :, 0:3]

Out[43]:

array([[ 0,  1,  2],
        [ 4,  5,  6],
        [ 8,  9, 10]])

 

 

 

 

 

 Python NumPy 배열 Indexing과 R의 행렬 Indexing 비교

 

마지막으로, R을 사용하면서 Python을 사용하는 분이라면 indexing이 처음에 혼란스러울 것입니다. 

저는 R indexing이 훨씬 더 쉬운데요, 여러분은 어떤지 모르겠습니다.  Python indexing은 '0'부터 시작하는 것도 어색하고, '0:3'이라고 했을 때 '3' 위치는 포함하지 않는 것도 어색합니다.  Python indexing 할 때는 항상 긴장하고, 실수 하지 않기 위해 머리 써야 해서 피곤합니다. -_-;;;  

(Java 나 C 프로그래밍 하셨던 분이라면 Python indexing이 더 쉽고 R indexing이 혼란스럽다고 하겠지요? ㅎㅎ)

 

아래에 Python NumPy 2차원 배열 indexing과 똑같은 결과를 얻을 수 있는 R의 행렬 indexing을 비교해보았습니다.

 

 Python NumPy : Indexing of 2D array

R : Indexing of Matrix 

 

In [44]: d = np.arange(20).reshape(4, 5)


In [45]: d

Out[45]:

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


In [46]: d[0:3, 1:3]

Out[46]:

array([[ 1,  2],
        [ 6,  7],
        [11, 12]])

 

 

> R_matrix_4_5 <- matrix(0:19, 
+                        nrow=4, 
+                        byrow=T)
>
> R_matrix_4_5 [,1] [,2] [,3] [,4] [,5] [1,] 0 1 2 3 4 [2,] 5 6 7 8 9 [3,] 10 11 12 13 14 [4,] 15 16 17 18 19 > > R_matrix_4_5[1:3, 2:3] [,1] [,2] [1,] 1 2 [2,] 6 7 [3,] 11 12

 

 

 

다음번 포스팅에서는

 

 - Boolean Indexing

 - Fancy Indexing

 

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

 

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

 

 

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by R Friend R_Friend


티스토리 툴바