이번 포스팅에서는 Python numpy 배열을 정렬(array sorting)하는 방법에 대해서 소개하겠습니다.

 

- (1) 1차원 배열 정렬 : np.sort(x)

- (2) 1차원 배열 거꾸로 정렬 : np.sort(x)[::-1] , x[np.argsort(-x)]

- (3) 2차원 배열 열 축 기준으로 정렬 : np.sort(x, axis=1)

- (4) 2차원 배열 행 축 기준으로 정렬 : np.sort(x, axis=0)

- (5) 2차원 배열 행 축 기준으로 거꾸로 정렬 : np.sort(x, axis=0)[::-1]

 


[ Python Numpy 배열 정렬: np.sort() ]

 



  (1) 1차원 배열 정렬 : np.sort(x)

 

 

In [1]: import numpy as np


In [2]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [3]: np.sort(x)

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

 

 

 

참고로, np.sort(x) 메소드는 원래의 배열은 그대로 둔채로 정렬이 된 결과를 복사본으로 반환합니다.

반면에 x.sort() 메소드는 원래의 배열 자체를 정렬합니다.

 

np.sort(x) 

=> 원래 배열은 그래로, 정렬 결과 복사본 반환

x.sort()

=> 배열 자체를 정렬

 

In [2]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [3]: np.sort(x)

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


In [4]: x

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

 

 In [5]: x = np.array([4, 2, 6, 5, 1, 3, 0])

   ...:


In [6]: x.sort()


In [7]: x

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

 

 

 

 (2) 1차원 배열 거꾸로 정렬 : np.sort(x)[::-1] , x[np.argsort(-x)]

 

배열을 거꾸로 정렬하는 방법에는 2가지가 있습니다.

 

(2-1) np.sort(x)[::-1] : 정렬을 한 후 mirror view 생성

 

 

In [8]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [9]: x_reverse_1 = np.sort(x)[::-1] # mirror view


In [10]: x_reverse_1

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

 

 

 

(2-2) x[np.argsort(-x)] : np.argsort() 로 index를 받아서 indexing 해오기

 

 

In [11]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [12]: x_reverse_2 = x[np.argsort(-x)] # copy of reversed sorting


In [13]: x_reverse_2

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

 

 



(3) 2차원 배열 열 축 기준으로 정렬 (from left to right) : np.sort(x, axis=1)


'axis = 1' 옵션을 주면 열 축을 기준으로, 좌에서 우로 (from left to right) 정렬을 합니다. 

이게 좀 헷갈릴 수 있는데요, 아래 예제로 확인해 보시기 바랍니다. 



In [14]: x2 = np.array([[2, 1, 6],

    ...:                       [0, 7, 4],

    ...:                       [5, 3, 2]])


In [15]: x2_sort_axis_1 = np.sort(x2, axis=1) # default


In [16]: x2_sort_axis_1

Out[16]:

array([[1, 2, 6],

        [0, 4, 7],

        [2, 3, 5]])

 




 (4) 2차원 배열 행 축 기준으로 정렬 (from top to bottom) : np.sort(x, axis=0)



In [17]: x2 = np.array([[2, 1, 6],

    ...:                       [0, 7, 4],

    ...:                       [5, 3, 2]])


In [18]: x2_sort_axis_0 = np.sort(x2, axis=0)


In [19]: x2_sort_axis_0

Out[19]:

array([[0, 1, 2],

        [2, 3, 4],

        [5, 7, 6]])

 




 (5) 2차원 배열 열 축 기준으로 거꾸로 정렬 (from bottom to top, reversely) 

     : np.sort(x, axis=1)[::-1]



In [20]: x2 = np.array([[2, 1, 6],

    ...:                       [0, 7, 4],

    ...:                       [5, 3, 2]])


In [21]: x2_sort_axis_0_reverse = np.sort(x2, axis=0)[::-1]


In [22]: x2_sort_axis_0_reverse

Out[22]:

array([[5, 7, 6],

        [2, 3, 4],

        [0, 1, 2]])

 


 

참고로 Python

 - (1) DataFrame 정렬 : DataFrame.sort_values()

 - (2) Tuple 정렬 : sorted(tuple, key)

 - (3) List 정렬 : list.sort(), sorted(list)

http://rfriend.tistory.com/281  을 참고하시기 바랍니다.


사전 자료형(Dictionary)의 키, 값 기준 정렬은 https://rfriend.tistory.com/473 를 참고하세요. 


데이터 형태마다 정렬 함수, 메소드가 조금씩 달라서 매번 헷갈리곤 합니다. ㅜ_ㅜ

 

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

 

728x90
반응형
Posted by Rfriend
,

R 의 벡터나 데이터 프레임을 특정 기준에 따라서 정렬하는 방법에 대해여 알아 보도록 하겠습니다.  SAS를 사용해본 분석가라면 두개 이상의 데이터 셋을 특정 기준으로 merge() 하기 전에 정렬 sort 를 실행해봤을 겁니다.  데이터셋 사이즈가 커지면 merge 하기 전 sort 하느라 시간 많이 잡아먹곤 해서 퇴근하기 전이나 점심먹으러 가기 전에 sorting 돌려놓고 갔던 경험이 있지 않을까 추측해봅니다.  (참고로, R에서는 merge 할때 사전 sorting이 필요 없음)

 

R에서는 데이터 정렬을 위해 sort()와 order() 두개의 함수를 제공하는데요, sort()는 정렬된 값을 순서대로 보여주는 반면에, order()는 데이터 크기의 색인을 제공합니다.  order()가 색인을 제공한다는게 무슨 말인지 잘 이해가 안될 수도 있는데요, 아래 예시를 보면서 설명드리겠습니다.

 

 

 R 벡터, 데이터 프레임 정렬 : sort(), order()

 

 

예시를 위해 세개의 벡터(숫자형 2개, 문자형 1개)와 한개의 데이터 프레임을 만들어보겠습니다.

 

> v1 <- c(40, 30, 50, 50, 90, 40, 50)
> v2 <- c(5100, 6500, 2000, 2000, 9000, 4500, 3000)
> v3 <- c("A", "B", "A", "B", "A", "A", "B")
> v123 <- data.frame(v1, v2, v3)
> v123
  v1   v2 v3
1 40 5100  A
2 30 6500  B
3 50 2000  A
4 50 2000  B
5 90 9000  A
6 40 4500  A
7 50 3000  B

 

 

벡터의 정렬

 

 (1) 숫자 자체 정렬 sort()

 

> v1 [1] 40 30 50 50 90 40 50 >
>
sort(v1) # 오름차순 정렬 [1] 30 40 40 50 50 50 90 >

> sort(v1, decreasing = TRUE) # 내림차순 정렬 [1] 90 50 50 50 40 40 30

 

sort()의 디폴트 정렬순은 오름차순이 되겠습니다.  내림차순으로 하려면 decreasing = TRUE 라는 옵션을 붙여주면 됩니다.

 

 

(2) 정렬 색인 값 order()

 

> v1
[1] 40 30 50 50 90 40 50
> 
> order(v1)
[1] 2 1 6 3 4 7 5
> 

> v1[ order(v1) ] # sort(v1)과 결과 동일 [1] 30 40 40 50 50 50 90

 

 

order(v1) 했을 때 나오는 색인 숫자들 [1] 2 1 6 3 4 7 5 는 무슨 뜻이냐 하면요, v1 중 가장 작은 값(30)이 두번째에 있고, 두번째로 작은값(40)이 첫번째에 있고, 세번째로 작은 값(40)이 여섯번째에 있고.... 이런 뜻입니다.

 

따라서 v1[ order(v1) ] 처럼 v1의 요소를 order(v1)에서 제시한 정렬 색인으로 indexing을 해오면 (1)번의 sort(v1)과 동일한 결과를 얻을 수 있습니다.

 

그러면, 결과가 같은면 그냥 sort(v1)을 쓰면 되지 왜 굳이 order()를 구분해서 사용하고 또 배워야 하는지 의아할 수도 있겠습니다.  order()는 아래의 데이터 프레임에서의 정렬에서 사용하게 되며, sort()는 데이터 프레임에서는 사용할 수 없다는점 때문에 두개 다 배워두어야 합니다.

 

 

데이터 프레임의 정렬

 

> rm(v1, v2, v3) # 벡터 v1, v2, v3 제거
> attach(v123) # 데이터 프레임 활성화
> 

> # v123 데이터 프레임의 전체 행을 v1 오름차순, v2 내림차순, v3 오름차순의 순서대로 정렬

> v123_order <- v123[ order(v1, -v2, v3), ] >

> v123 # 원래 데이터셋 v1 v2 v3 1 40 5100 A 2 30 6500 B 3 50 2000 A 4 50 2000 B 5 90 9000 A 6 40 4500 A 7 50 3000 B >

> v123_order  # 정렬된 후의 데이터 셋
  v1   v2 v3
2 30 6500  B
1 40 5100  A
6 40 4500  A
7 50 3000  B
3 50 2000  A
4 50 2000  B
5 90 9000  A
> 
> detach(v123) 

 

위 예제에서 데이터 프레임 v123 의 행 전체를 v1 오름차순, v2 내림차순(변수 앞에 - 부호), v3 오름차순(문자형도 알파벳순 정렬 가능)의 순서대로 정렬하였습니다.

 

정렬된 후의 데이터 프레임 v123_order 의 제일 왼쪽의 row.names 가 order(v1, -v2, v3)의 색인 결과와 같게 정렬이 되어 있음을 알 수 있습니다. 

 

> order(v1, -v2, v3) [1] 2 1 6 7 3 4 5 >
>
row.names(v123_order) [1] "2" "1" "6" "7" "3" "4" "5" 

 

다시 한번 정리하자면, 데이터 프레임에서 정렬할 때는 order()로 정렬한 색인을 가져다가 index의 행의 위치 ( [, 열] 에 집어 넣고, 열 자리에는 비워둠으로써 [order(), ] 모든 열을 가져오게끔 해서 정렬을 키는 원리입니다.



plyr 패키지arrange() 함수를 사용해서 정렬하는 방법도 있습니다. 내림차순으로 정렬하고자 할 경우에는 desc() 옵션을 추가하면 됩니다.  arrange(data.frame, var1, desc(var2), ...) 이런 형식으로 사용하면 되겠습니다.  아래 예제는 위의 order와 indexing을 사용한 것과 동일한 경과를 얻었음을 알 수 있습니다. 


> library(plyr)

> arrange(v123, v1, desc(v2), v3)

  v1   v2 v3

1 30 6500  B

2 40 5100  A

3 40 4500  A

4 50 3000  B

5 50 2000  A

6 50 2000  B

7 90 9000  A 



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

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

728x90
반응형
Posted by Rfriend
,