'Boolean Indexing'에 해당되는 글 1건

  1. 2017.02.27 [Python Numpy] Boolean 조건문으로 배열 인덱싱 (Boolean Indexing)

지난번 포스팅에서 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 에 대해서 알아보겠습니다.

 

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

 

 

Posted by R Friend R_Friend