파이썬 넘파이(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 : 필드가 정의된 배열인 경우, 어느 필드를 기준으로 정렬할지 지정

2) 내림차순 정렬 방법 : 오름차순 정렬 후 슬라이싱으로 역순 적용
  • 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]] 원본복구


Next Post Previous Post
No Comment
Add Comment
comment url