[Python Numpy] Boolean 조건문으로 배열 인덱싱 (Boolean Indexing)
Python 분석과 프로그래밍/Python 데이터 전처리 2017. 2. 27. 00:09지난번 포스팅에서 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],
|
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'],
|
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],
# the same result with the above In [8]: arr[axis_ABC == 'A', :] Out[8]: array([[0, 1, 2, 3],
|
옆길로 조금 빠져보자면요, Boolean 조건으로 행(row) 전체를 indexing 하고, 콤마(comma) ',' 와 함께 콜론(colon) ':'으로 slicing을 하거나 정수(integer)로 열(column)을 indexing 하는 예를 들어보겠습니다.
# slicing with colon ':'
In [9]: arr[axis_ABC == 'A', :2] Out[9]: array([[0, 1],
# 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],
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],
# selecting all the rows except 'A' : ~(axisABC == 'A') In [12]: arr[~(axis_ABC == 'A')] Out[12]: array([[ 8, 9, 10, 11],
|
(3) 복수의 조건으로 배열의 특정 열 선별하기 : & (and), | (or) |
Boolean 조건문으로 두 개 이상의 복수개를 사용할 때가 있겠지요? & (and), | (or) operator로 복수의 조건문을 엮어서 indexing 하는 예를 들어보겠습니다.
In [3]: arr Out[3]: array([[ 0, 1, 2, 3],
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], In [14]: arr[(axis_ABC != 'A') & (axis_ABC != 'B')] Out[14]: array([[12, 13, 14, 15],
|
이때 유의할 게 있는데요, '&', '|' 대신에 '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],
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],
In [18]: arr[arr >= 100] = 0 In [19]: arr Out[19]: array([[ 0, 0, 0, 0],
In [20]: arr[(arr >= 8) & (arr <= 15)] = 10 In [21]: arr Out[21]: array([[ 0, 0, 0, 0],
|
다음번 포스팅에서는 특정 순서로 행과 열을 선택하는 Fancy Indexing 에 대해서 알아보겠습니다.
많은 도움 되었기를 바랍니다.