본문 바로가기
Python/Pandas

멀티인덱스와 인덱스 정렬, sort_index()메서드-pandas(46)

by 콩돌 2020. 12. 29.
반응형

파이썬 버전 3.8 기준

pandas 버전 1.2.0 기준


 멀티인덱스(MultiIndex)와 인덱스 정렬 sort_index()메서드


본 포스팅에서는 멀티인덱스(MultiIndex)와 인덱스를 정렬하는 방법에 해대 다뤄보도록 한다.

이를 위해 sort_index() 메서드를를 사용하고, 해당 메서드에 대한 설명을 해보도록 한다. 

추가적으로 is_lexsorted() 메서드를 이용한 인덱스가 정렬여부 확인 예제와 lexsort_depth 속성을 통해 멀티인덱스 정렬의 깊이를 확인할 수 있는 예제를 다루도록한다.

 

 MultiIndex와 Index의 정렬


멀티인덱스(MultiIndex)와 인덱스(index)의 정렬을 위해 sort_index() 메서드를 사용할 수 있다.

sort_index() 메서드는 주어진 축을 따라 레이블을 이용하여 정렬을 수행한다.

  ○ 이는 슬라이스나 인덱싱을 더 효율적으로 가능하게 한다.

 

sort_index() 메서드의 사용 형식은 다음과 같다.


메서드 사용 형식)

result=object.sort_index(axis=0, level=None, ascending=True, inplace=False)

 

각 입력 객체별 설명은 다음과 같다.

  ○ object: 메서드가 적용되는 객체로 DataFrame, Series 등이 해당된다.

  ○ level: 정렬을 할 레벨(level)을 선택한다.

  ○ axis: 메서드를 적용할 축을 입력받는다.

    ▷ 0 or 'index': 행의 인덱스를 정렬한다.(기본값)

    ▷ 1 or 'columns': 열의 인덱스를 정렬한다.

  ○ ascending: 오름차순/내림차순 정렬 여부를 결정한다.

    ▷ True: 오름차순으로 정렬한다.(기본값)

    ▷ False: 내림차순으로 정렬한다.

  ○ inplace: 원본객체를 변경할지 결정한다.

    ▷ True: 원본 객체를 정렬된 상태로 변경한다.

    ▷ False: 원본 객체를 변경하지 않는다. (기본값)

  

 MultiIndex의 정렬 예제

예제를 수행하기에 앞서 다음과 같이 모듈들을 import하고 예제용 Series를 정의하였다.

멀티인덱스가 아닌 일반 인덱스에는 level만 입력할 필요 없이 아래 예제들과 동일하게 적용하면되므로 인덱스에 대한 예제는 따로 수행하지 않는다.


모듈의 임폴트)

# pandas와 numpy의 import

In[2]: import numpy as np

In[3]: import pandas as pd

In[4]: import random


# 예제용 인덱스 입력 튜플 정의

In[5]: ex_tuple=[('A','a'), ('A','b'), ('B','a'), ('B','b'), ('C','a'), ('C','b'), ('D','a'), ('D','b')]

In[6]: random.shuffle(ex_tuple)

In[7]: ex_tuple

Out[7]: 

[('A', 'a'), ('C', 'a'), ('A', 'b'), ('B', 'b'), ('B', 'a'), ('D', 'b'), ('D', 'a'), ('C', 'b')]


# 예제용 Series 정의

In[8]: ex_s = pd.Series([0,1,2,3,4,5,6,7], index=pd.MultiIndex.from_tuples(ex_tuple))

In[9]: ex_s

Out[9]: 

A  a    0

C  a    1

A  b    2

B  b    3

   a    4

D  b    5

   a    6

C  b    7

dtype: int64

 

아래는 Series에 sort_index()를 적용한 예제를 보여준다.

 

메서드 적용 예제)

# sort_index() 메서드 적용 예제

In[10]: ex_s.sort_index()

Out[10]: 

A  a    0

   b    2

B  a    4

   b    3

C  a    1

   b    7

D  a    6

   b    5

dtype: int64


# level 입력변수 사용 예제 1

In[11]: ex_s.sort_index(level=0)

Out[11]: 

A  a    0

   b    2

B  a    4

   b    3

C  a    1

   b    7

D  a    6

   b    5

dtype: int64


# level 입력변수 사용 예제 2

In[12]: ex_s.sort_index(level=1)

Out[12]: 

A  a    0

B  a    4

C  a    1

D  a    6

A  b    2

B  b    3

C  b    7

D  b    5

dtype: int64

 

만약 MultiIndex의 레벨에 이름이 있다면, 사용자는 또한 단계의 이름을 sort_index() 메서드에 입력할 수 있다.

 

level 변수에 이름(문자열) 사용 예제 )

# 각 Level의 이름입력

In[13]: ex_s.index.set_names(['one', 'two'], inplace=True)


# level 변수에 이름(문자열) 사용 예제 1

In[14]: ex_s.sort_index(level='one')

Out[14]: 

one  two

A    a      0

     b      2

B    a      4

     b      3

C    a      1

     b      7

D    a      6

     b      5

dtype: int64


# level 변수에 이름(문자열) 사용 예제 2

In[15]: ex_s.sort_index(level='two')

Out[15]: 

one  two

A    a      0

B    a      4

C    a      1

D    a      6

A    b      2

B    b      3

C    b      7

D    b      5

dtype: int64

 

DataFrame과 같은 더 높은 차원의 객체에서는, 각 축에 따라 그리고 레벨(level)에 따라 인덱스를 정렬할 수 있다.  

 

DataFrame에서의 정렬 예제)

# 예제용 DataFrame의 정의

In[16]: ex_df=pd.DataFrame([range(x*8,x*8+8) for x in range(4)], index= ['b', 'd', 'c', 'a'], columns= pd.MultiIndex.from_tuples(ex_tuple))

In[17]: ex_df

Out[17]: 

    A   C   A   B       D       C

    a   a   b   b   a   b   a   b

b   0   1   2   3   4   5   6   7

d   8   9  10  11  12  13  14  15

c  16  17  18  19  20  21  22  23

a  24  25  26  27  28  29  30  31


# axis 변수의 사용 예제 1

In[18]: ex_df.sort_index(axis=1)

Out[18]: 

    A       B       C       D    

    a   b   a   b   a   b   a   b

b   0   2   4   3   1   7   6   5

d   8  10  12  11   9  15  14  13

c  16  18  20  19  17  23  22  21

a  24  26  28  27  25  31  30  29


# axis 변수의 사용 예제 2

In[19]: ex_df.sort_index(axis=0)

Out[19]: 

    A   C   A   B       D       C

    a   a   b   b   a   b   a   b

a  24  25  26  27  28  29  30  31

b   0   1   2   3   4   5   6   7

c  16  17  18  19  20  21  22  23

d   8   9  10  11  12  13  14  15


# axis 변수와 level변수의 동시 사용 예제 1

In[20]: ex_df.sort_index(level=0, axis=1)

Out[20]: 

    A       B       C       D    

    a   b   a   b   a   b   a   b

b   0   2   4   3   1   7   6   5

d   8  10  12  11   9  15  14  13

c  16  18  20  19  17  23  22  21

a  24  26  28  27  25  31  30  29


# axis 변수와 level변수의 동시 사용 예제 2

In[21]: ex_df.sort_index(level=1, axis=1)

Out[21]: 

    A   B   C   D   A   B   C   D

    a   a   a   a   b   b   b   b

b   0   4   1   6   2   3   7   5

d   8  12   9  14  10  11  15  13

c  16  20  17  22  18  19  23  21

a  24  28  25  30  26  27  31  29

 

데이터가 정렬되지 않았을 경우에도 인덱싱은 작동한다.

그러나 비효율적이며 이때 경우에 따라선 PerformanceWarning 메세지를 출력한다.

이것은 view가 아닌 데이터의 복사본을 반환한다.

 

비정렬된 멀티인덱스에서의 인덱싱)

In[22]: ex_df.loc(axis=1)[('C','b')]

Out[22]: 

b     7

d    15

c    23

a    31

Name: (C, b), dtype: int64

 

게다가 사용자는 완전히 정렬되지 않은 인덱스에 슬라이싱을 시도할 경우 다음과 같은 메세지를 출력한다.

 

비정렬된 멀티인덱스에서 슬라이싱)

In[23]: ex_df.loc(axis=1)[('A','b'):('C','b')]

pandas.errors.UnsortedIndexError: 'Key length (2) was greater than MultiIndex lexsort depth (0)'

 

정렬을 수행한 경우에는 슬라이싱이 제대로 작동한다.

 

정렬된 멀티인덱스에서의 슬라이싱)

# pandas와 numpy의 import

In[24]: ex_df.sort_index(axis=1).loc(axis=1)[('A','b'):('C','b')]

Out[24]: 

    A   B       C    

    b   a   b   a   b

b   2   4   3   1   7

d  10  12  11   9  15

c  18  20  19  17  23

a  26  28  27  25  31

 

MultiIndex에서 is_lexsorted() 메서드는 인덱스가 정렬여부를 알려준다.

그리고 lexsort_depth 속성은 정렬의 깊이를 반환한다. 


is_lexsorted() 메서드 및 lexsort_depth 메서드 사용 예제)

# is_lexsorted() 메서드 사용 예제 

In[25]: ex_df.columns.is_lexsorted()

Out[25]: False


In[26]: ex_df.sort_index(axis=1).columns.is_lexsorted()

Out[26]: True


# lexsort_depth 메서드 사용 예제 

In[27]: ex_df.columns.lexsort_depth

Out[27]: 0


In[28]: ex_df.sort_index(axis=1).columns.lexsort_depth

Out[28]: 2

 

ascending 입력변수를 이용하여 오름차순 혹은 내림차순으로 정렬을 조정할 수 있다.

기본값은 True로 오름차순으로 정렬하며 False을 할 경우 내림차순으로 정렬한다.

 

ascending 입력변수 사용 예제)

In[29]: ex_df.sort_index(axis=1, ascending=False)

Out[29]: 

    D       C       B       A    

    b   a   b   a   b   a   b   a

b   5   6   7   1   3   4   2   0

d  13  14  15   9  11  12  10   8

c  21  22  23  17  19  20  18  16

a  29  30  31  25  27  28  26  24

 

inplace 입력변수를 사용하여 메서드가 적용될 때 원본객체를 변경이 적용되게 할 수 있다.

기본값은 False로 변경이 적용되지 않는다.

 

inplace 입력변수 사용 예제)

In[30]: ex_df.sort_index(axis=1, inplace=True)

In[31]: ex_df

Out[31]: 

    A       B       C       D    

    a   b   a   b   a   b   a   b

b   0   2   4   3   1   7   6   5

d   8  10  12  11   9  15  14  13

c  16  18  20  19  17  23  22  21

a  24  26  28  27  25  31  30  29

 

 

 메서드 세부사항

 

 DataFrame.sort_index(self, axis=0, level=None, ascending=True, inplace=False, kind='quicksort', na_position='last', sort_remaining=True, by=None)

축을 따라서 레이블을 통해 객체를 정렬한다.


axis: {0, 1, 'index', 'columns'}

기본값은 0이다.

정렬하려하는 축을 명시한다.

0은 열(혹은 인덱스)을, 1은 열을 나타낸다.

 

level: int, level name, list of ints, list of label names

만약에 None이 아니라면 명시된 인덱스 단계에서 값들을 정렬한다.


ascending: bool

기본값은 True이다.

오름차순(True)으로 정렬할지, 내림차순(False)으로 정렬할지 결정한다.


inplace: bool

기본값은 False이다.

True일 경우, 원본 객체를 수정한다.


kind: {'quicksort', 'mergesort', 'heapsort'}

기본값은 'quicksort'이다.

정렬알고리즘을 선택한다.

자세한 내용은 ndarray.np.sort관련 설명을 참고하자.

megesort는 안정적인 알고리즘이다.

DataFrame에 대해서 이 옵션은 오직 하나의 열 혹은 레이블만 정렬할때 적용된다.


na_position: {'first', 'last'}

기본값은 'last'이다.

'first'일 경우 NaN 값들을 시작지점에 둔다.

'last'일 경우 NaN값들을 마지막 지점에 둔다.

MultiIndex에서는 사용될 수 없다.


sort_remaining: bool

기본값은 True이다.

True 및 단계 및 인덱스 별 정렬이 MultiIndex인 경우, 지정된 단계를 기준으로 정렬 한 후 다른 단계도 순서대로 정렬한다.

 


 MultiIndex.is_lexsorted(self)

만약 코드가 사전형식(알파벳 순)으로 정렬되어 있다면 True를 반환한다.

 

 

 

 

 

 

 참고자료

  https://pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html

  https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_index.html

  https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.MultiIndex.is_lexsorted.html

 

 

 

 

 


반응형

댓글