파이썬 넘파이(Numpy) 함수 총정리4 : 정렬 및 조건 검색, 고유값 찾기 (sort, argsort, where, unique)
데이터 분석을 하게 되면 수만 개의 데이터가 담긴 배열에서 내가 원하는 조건의 데이터만 뽑아내거나, 데이터를 크기순으로 정렬해야 할 때가 자주 있습니다.
이 글에서는 넘파이 함수 총정리 제 4탄으로, 실무 데이터 분석에서 가장 활용도가 높은 배열 정렬(Sort)과 조건 검색(Search) 함수들을 정리해 보도록 하겠습니다.
![]() |
| 넘파이(Numpy) 정렬 및 조건검색, 고유값 찾기 함수 |
01. 배열 정렬하기
데이터를 오름차순이나 내림차순으로 정렬하고자 할 때는 sort( ) 함수를 사용합니다. sort( ) 함수는 기본적으로 오름차순으로 정렬합니다. 하지만, 넘파이에는 별도의 내림차순 함수나 옵션이 없어, 내림차순으로 정렬하고자 할 때는 오름차순으로 정렬 후 뒤에 슬라이싱을 이용하여 역순으로 뒤집어 내림차순 정렬이 되도록 사용합니다.
1) sort( ) : 정렬 (오름차순)
- np.sort(a, axis=-1, kind=None, order=None) : 복사본 반환
-
a.sort(axis=-1, kind=None, order=None) : 원본 수정
- a : 입력 배열
- axis : 정렬 기준 축
- kind : 정렬 알고리즘 선택 ('quicksort' - 기본값, 'mergesort', 'heapsort', 'stable')
- order : 필드가 정의된 배열인 경우, 어느 필드를 기준으로 정렬할지 지정
- np.sort(a1)[ : : -1] : 1차원 내림차순
- np.sort(a2)[ : : -1, :] : 2차원 내림차순, 위아래 행만 역순 적용
-
np.sort(a2)[ :, : : -1] : 2차원 내림차순, 좌우
열만 역순 적용
- [start : end : step] : 기본값 [None(시작위치) : None(끝위치) : 1]
(ex1) [ : : -1 ] = [None : None : -1]
(ex2) [ : ] = [None : None : 1]
[1차원 배열 정렬]
a1 = np.array([2, 4, 3, 1])
print(np.sort(a1)) # 결과: [1 2 3 4]
print(np.sort(a1)[::-1]) # 결과: [4 3 2 1]
[2차원 배열 정렬]
a2 = np.array([[4, 2, 6],
[1, 5, 3],
[8, 9, 7]])
print(np.sort(a2)) # 결과: [[2 4 6]
print(np.sort(a2, axis=1)) # 두개 [1 3 5]
# 동일 [7 8 9]]
print(np.sort(a2)[:, ::-1]) # 결과: [[6 4 2]
print(np.sort(a2, axis=1)[:, ::-1]) # 두개 [5 3 1]
# 동일 [9 8 7]]
print(np.sort(a2, axis=0)) # 결과: [[1 2 3] (1열 정렬값)
# [4 5 6] (2열 정렬값)
# [8 9 7]] (3열 정렬값)
print(np.sort(a2, axis=0)[::-1, :]) # 결과: [[8 9 7]
# [4 5 6]
# [1 2 3]]
02. 인덱스를 반환하는 정렬
np.argsort( )는 정렬된 값 자체가 아니라, 정렬 되었을 때 원래 인덱스(위치번호)를 반환하는 함수입니다. 여러 데이터를 연동해서 정렬해야 할 경우 필수적으로 사용되기 때문에 꼭 알아두어야 합니다.
1) argsort( ) : 인덱스를 반환하는 정렬
-
np.argsort(a, axis=-1, kind=None, order=None)
- a : 입력 배열
- axis : 정렬 기준 축 (기본값 : -1, 마지막 축이며, None 설정시 1차원으로 평탄화 후 정렬)
- kind : 정렬 알고리즘 선택 ('quicksort' - 기본값, 'mergesort', 'heapsort', 'stable')
- order : 필드가 정의된 배열인 경우, 어느 필드를 기준으로 정렬할지 지정
2) 정렬된 값 출력방법
- argsort( ) 함수로 얻은 인덱스를 원래 배열에 팬시 인덱싱(Fancy Indexing)을 적용하면 실제 정렬된 값을 얻을 수 있습니다.
[1차원 배열 정렬]
a = np.array([2, 4, 3, 1])
r1 = np.argsort(a)
r2 = np.argsort(-a)
print(r1, r2) # 결과: [3 0 2 1] [1 2 0 3]
print(a[r1], a[r2]) # 결과: [1 2 3 4] [4 3 2 1]
[2차원 배열 정렬]
a = np.array([[1, 90],
[2, 40],
[3, 70]])
r1 = np.argsort(a[:, 1]) # 2번째 열기준으로 정렬
r2 = np.argsort(-a[:, 1]) # 2번째 열기준으로 정렬
print(r1) # 결과: [1 2 0]
print(r2) # 결과: [0 2 1]
print(a[r1]) # 결과: [[ 2 40]
# [ 3 70]
# [ 1 90]]
print(a[r2]) # 결과: [[ 1 90]
# [ 3 70]
# [ 2 40]]
03. 조건 검색 및 위치 찾기
조건에 맞는 데이터만 골라내거나, 그 값의 위치를 찾아내고자 할 때는 where( ) 함수를 사용합니다. 인자를 3개(조건식, 참값, 거짓값) 사용하면 각 요소를 조건식에 대입하여 참 또는 거짓값으로 대체하여 반환하고, 인자를 1개(조건식)만 사용하면 조건에 맞는 요소의 인덱스(위치)를 반환합니다.
1) where( ) : 조건에 따라 값을 선택하거나, 조건에 맞는 인덱스를 찾는 함수
-
np.where(condition, x, y) : 각 요소를 조건에 맞는
값을 선택하여 반환함
- condition : 참(true)인지 거짓(false)인지 판단할 조건식
- x : 조건이 참(true)일 때 선택할 값
- y : 조건이 거짓(false)일 때 선택할 값 -
np.where(condition) : 조건에 맞는 요소의 인덱스(위치)를
반환함
- condition : 참(true)인지 거짓(false)인지 판단할 조건식
a1 = np.array([10, 11, 12, 13, 14, 15])
a2 = np.array([[10, 11], [12, 13], [14, 15]])
print(np.where(a1>12)) # 결과: (array([3, 4, 5]),)
print(np.where(a1>12, 'P', 'F')) # 결과: ['F' 'F' 'F' 'P' 'P' 'P']
print(np.where(a2>12)) # 결과: (array([1, 2, 2]), [행]
# array([1, 0, 1])) [열]
print(np.where(a2>12, 'P', 'F')) # 결과: [['F' 'F']
# ['F' 'P']
# ['P' 'P']]
2) any( ) : 배열의 요소 중 하나라도 참이 있으면 True를 반환하는 함수
-
np.any(a, axis=None, keepdims=False, where=True)
- a : 입력 배열 (조건식을 지정하여 불리언 배열로 변환된 배열 입력)
- axis : 어느 축을 기준으로 계산할지 지정 (기본값 : None, 전체요소 기준)
- keepdims : True로 지정하면 결과 배열의 차원을 원본과 동일하게 유지함
- where : 조건이 참(True)인 요소만 계산에 포함시킴
a = np.array([[1, 2, 3],[4, 5, 6]])
print(np.any(a > 3)) # 결과: True
print(np.any(a < 3)) # 결과: True
print(np.any(a > 0)) # 결과: True
print(np.any(a < 0)) # 결과: False
print(np.any(a < 3 , axis=0)) # 결과: [True True False]
print(np.any(a < 3 , axis=1)) # 결과: [True False]
3) all( ) : 배열의 모든 요소가 참인 경우만 True를 반환하는 함수
-
np.all(a, axis=None, keepdims=False, where=True)
- a : 입력 배열 (조건식을 지정하여 불리언 배열로 변환된 배열 입력)
- axis : 어느 축을 기준으로 계산할지 지정 (기본값 : None, 전체요소 기준)
- keepdims : True로 지정하면 결과 배열의 차원을 원본과 동일하게 유지함
- where : 조건이 참(True)인 요소만 계산에 포함시킴
a = np.array([[1, 2, 3],[4, 5, 6]])
print(np.all(a > 3)) # 결과: False
print(np.all(a < 3)) # 결과: False
print(np.all(a > 0)) # 결과: True
print(np.all(a < 0)) # 결과: False
print(np.all(a < 5 , axis=0)) # 결과: [True False False]
print(np.all(a < 5 , axis=1)) # 결과: [True False]
04. 최대/최소값 위치 찾기
최대값과 최소값의 인덱스(위치)를 반환하는 함수입니다.
1) argmin( ) : 최소값이 위치한 인덱스 번호를 반환합니다.
- np.argmin(a, axis=None, keepdims=False)
-
a.argmin(axis=None, keepdims=False)
- a : 입력 배열
- axis : 어느 축을 기준으로 계산할지 지정 (기본값 : None, 전체요소 기준)
- keepdims : True로 지정하면 결과 배열의 차원을 원본과 동일하게 유지함
a1 = np.array([9, 8, 7, 1, 2, 3])
a2 = np.array([[9, 8, 7], [1, 2, 3]])
print(a1.argmin()) # 결과: 3
print(a1.argmin(keepdims=True)) # 결과: [3]
print(a2.argmin()) # 결과: 3
print(a2.argmin(axis=0)) # 결과: [1 1 1]
print(a2.argmin(axis=1)) # 결과: [2 0]
print(a2.argmin(axis=1, keepdims=True)) # 결과: [[2][0]]
2) argmax( ) : 최대값이 위치한 인덱스 번호를 반환합니다.
- np.argmax(a, axis=None, keepdims=False)
-
a.argmax(axis=None, keepdims=False)
- a : 입력 배열
- axis : 어느 축을 기준으로 계산할지 지정 (기본값 : None, 전체요소 기준)
- keepdims : True로 지정하면 결과 배열의 차원을 원본과 동일하게 유지함
a1 = np.array([9, 8, 7, 1, 2, 3])
a2 = np.array([[9, 8, 7], [1, 2, 3]])
print(a1.argmax()) # 결과: 0
print(a1.argmax(keepdims=True)) # 결과: [0]
print(a2.argmax()) # 결과: 0
print(a2.argmax(axis=0)) # 결과: [0 0 0]
print(a2.argmax(axis=1)) # 결과: [0 2]
print(a2.argmax(axis=1, keepdims=True)) # 결과: [[0][2]]
05. 고유값 찾기
배열의 데이터에서 중복된 요소를 제거하고 고유한 값들만 오름차순으로 정렬하여 반환하는 함수입니다.
1) unique( ) : 중복된 요소를 제거하고 고유한 값들을 반환하는 함수
-
np.unique(ar, return_index=False, return_inverse=False,
return_counts=False, axis=None)
- ar : 입력 배열
- return_index : True일 경우, 각 고유값이 원본 배열에서 처음 등장한 인덱스를 함께 반환합니다.
- return_inverse : True일 경우, 고유값 배열로부터 원본 배열을 재구성할 수 있는 인덱스 배열을 함께 반환합니다.
- return_counts : True일 경우, 각 고유값이 원본 배열에 등장한 빈도수를 함께 반환합니다.
- axis : 고유값을 찾을 기준 축을 지정합니다. (미지정시 1차원으로 평탄화 처리함)
a = np.array([[5, 3, 1],[3, 3, 2],[3, 7, 5]])
r = np.unique(a)
print(r) # 결과: [1 2 3 5 7]
values, counts = np.unique(a, return_counts=True)
print(values) # 결과: [1 2 3 5 7]
print(counts) # 결과: [1 1 4 2 1]
values, indices = np.unique(a, return_index=True)
print(values) # 결과: [1 2 3 5 7]
print(indices) # 결과: [2 5 1 0 7]
values, inverse = np.unique(a, return_inverse=True)
print(values) # 결과: [1 2 3 5 7]
print(inverse) # 결과: [[3 2 0][2 2 1][2 4 3]]
print(values[inverse]) # 결과: [[5 3 1][3 3 2][3 7 5]] 원본복구
