본문 바로가기
Python/Pandas

카테고리 인덱스(CategoricalIndex) 기반 중복인덱싱-pandas(49)

by 콩돌 2021. 1. 6.
반응형

파이썬 버전 3.8 기준

pandas 버전 1.2.0 기준


 카테고리 인덱스(CategoricalIndex)기반 중복인덱싱

 

본 포스팅에서는 Pandas에서 제공하는 카테고리 인덱스(CategoricalIndex) 타입에 대해 다루도록 한다.

 

 

 CategoricalIndex

 
CategoricalIndex는 카테고리 인덱스로 pandas에서 제공하는 인덱스 유형 중 하나이다. 

이 인덱스는 카테고리로 나누어 값을 저장할 수 있는 인덱스를 형성시킬 수 있다.

  ○ 중복되는 인덱스에 여러가지 값을 담을 수 있으며 해당 인덱스는 카테고리로 인식된다.

  ○ 따라서 복사본(중복)을 사용한 인덱싱을 필요로 할 때 유용하다.

  ○ 효율적인 인덱싱과 많은 수의 중복된 요소를 포함하는 인덱스의 저장을 가능하게 한다.

 

 

 CategoricalIndex 예제

다음은 예제수행을 위한  카테고리 인덱스를 가지는 DataFrame의 생성하는 예제이다.


모듈의 임폴트 및 카테고리 인덱스를 가지는 DataFrame의 생성)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np

In[4]: from pandas.api.types import CategoricalDtype


# DataFrame의 생성

In[5]: ex_df = pd.DataFrame({"A": np.arange(6), "B":list("cbaaba")})

In[6]: ex_df

Out[6]: 

   A  B

0  0  c

1  1  b

2  2  a

3  3  a

4  4  b

5  5  a


In[7]: ex_df.dtypes

Out[7]: 

A     int32

B    object

dtype: object


# 'B' 객체의 카테고리 인덱스 타입으로의 변경

In[8]: ex_df["B"] = ex_df["B"].astype(CategoricalDtype(list("cab")))

In[9]: ex_df

Out[9]: 

   A  B

0  0  c

1  1  b

2  2  a

3  3  a

4  4  b

5  5  a


In[10]: ex_df.dtypes

Out[10]: 

A       int32

B    category

dtype: object


In[11]: ex_df["B"].cat.categories

Out[11]: Index(['c', 'a', 'b'], dtype='object')

 

 

위의 예제에서 'B' 칼럼의 객체를 인덱스로 다음과 같이 세팅할 수 있다.

세팅을 완료하면 해당 객체의 인덱스는 CategoricalIndex이 된다.

  

index의 세팅)

# Index의 세팅

In[12]: ex_df2=ex_df.set_index('B')


# 세팅된 Index의 확인

In[13]: ex_df2.index

Out[13]: CategoricalIndex(['c', 'b', 'a', 'a', 'b', 'a'], categories=['c', 'a', 'b'], ordered=False, name='B', dtype='category')


In[14]ex_df2

Out[14]: 

   A

B   

c  0

b  1

a  2

a  3

b  4

a  5

 

 

__getiem__ / .iloc / .loc 메서드를 사용한 인덱싱은 복사본을 사용한 인덱스와 유사하게 작동한다.

인덱서는 반드시 카테고리 안에 있거나, 해당 연산은 KeyError를 일으킨다.


인덱싱 예제)

In[15]: ex_df2.loc['a']

Out[15]: 

   A

B   

a  2

a  3

a  5

 

 

CategoricalIndex는 인덱싱 이후 보존된다.


인덱싱 이후의 카테고리 보존 예)

In[16]: ex_df2.loc['a'].index

Out[16]: CategoricalIndex(['a', 'a', 'a'], categories=['c', 'a', 'b'], ordered=False, name='B', dtype='category')

 

 

인덱싱을 정렬하는 것은 카테고리의 순서에 따라 정렬한다.

  ○ 예를들어 현재 수행 중인 예제를 기준으로는 카테고리 순서는 CategoricalDtype(list('cab'))을 사용한 인덱스를 다시 불러온다. 그래서 정렬된 순서는 cab이다.


카테고리 인덱스 정렬 예)

In[17]: ex_df2.sort_index()

Out[17]: 

   A

B   

c  0

a  2

a  3

a  5

b  1

b  4

 

 

인덱스에서 Groupby 연산을 수행할 때 인덱스의 성질 또한 보존한다.

 

groupby 메서드 사용 예제)

In[18]: ex_df2.groupby(level=0).sum()

Out[18]: 

    A

B    

c   0

a  10

b   5


In[19]: ex_df2.groupby(level=0).sum().index

Out[19]: CategoricalIndex(['c', 'a', 'b'], categories=['c', 'a', 'b'], ordered=False, name='B', dtype='category')

 

 

reindex() 메서드는 입력된 인덱서의 자료형에 기반하여 결과로 나오는 인덱스를 반환한다.

리스트를 입력하는 것은 평범한 인덱스를 반환하는 반면에,

Categorical 을 사용한 인덱싱은 CategoricalIndex를 반환한다. 

  ○ 입력되는 Categorical dtype의 카테고리에 따라 인덱스되어진다.

이것은 심지어 카테고리에 없는 값을 사용한 임의의 인덱스를 할 수 있도록 한다.

  ○ 어떻게 다른 pandas 인덱스를 다시 인덱스 할 수 있을지와 유사하다. 


reindex 메서드 사용 예제)

# 예제용 DataFrame의 생성

In[20]: ex_df3 = pd.DataFrame({"A": np.arange(3), "B": pd.Series(list("abc")).astype("category")})


# 일반적인 reindex 메서드 사용

In[21]: ex_df3.reindex(["a", "d"])

Out[21]: 

    A    B

a NaN  NaN

d NaN  NaN


# ex1: 리스트를 사용한 reindex 메서드 사용 예제

In[22]: ex_df3=ex_df3.set_index("B")

In[23]: ex_df3.reindex(["a", "d"])

Out[23]: 

     A

B     

a  0.0

d  NaN


ex1: 인덱스 타입 확인: 일반인덱스

In[24]: ex_df3.reindex(["a", "d"]).index

Out[24]: Index(['a', 'd'], dtype='object', name='B')


ex2: 카테고리 인덱스를 사용한 reindex 메서드 사용 예제

In[25]: ex_df3.reindex(pd.Categorical(["a", "d"], categories=list("abd")))

Out[25]: 

     A

B     

a  0.0

d  NaN


ex2: 인덱스 타입 확인: 일반인덱스

In[26]: ex_df3.reindex(pd.Categorical(["a", "e"], categories=list("abe"))).index

Out[26]: CategoricalIndex(['a', 'e'], categories=['a', 'b', 'e'], ordered=False, name='B', dtype='category')


 

※ 경고

CategoricalIndex에서의 재형성과 비교 연산은 반드시 같은 카테고리를 가져야하며, 그렇지 않으면, TypeError가 발생한다.

 

예제)

# 예제용 DataFrame 생성 1

In[27]: ex_df4 = pd.DataFrame({"A": np.arange(2), "B": list("ba")})

In[28]: ex_df4["B"] = ex_df4["B"].astype(CategoricalDtype(list("ab")))

In[29]: ex_df4 = ex_df4.set_index("B")

In[30]: ex_df4.index

Out[30]: CategoricalIndex(['b', 'a'], categories=['a', 'b'], ordered=False, name='B', dtype='category')


# 예제용 DataFrame 생성 2

In[31]: ex_df5 = pd.DataFrame({"A": np.arange(2), "B": list("bc")})

In[32]: ex_df5["B"] = ex_df5["B"].astype(CategoricalDtype(list("bc")))

In[33]: ex_df5 = ex_df5.set_index("B")

In[34]: ex_df5.index

Out[34]: CategoricalIndex(['b', 'c'], categories=['b', 'c'], ordered=False, name='B', dtype='category')


# 메서드 실패 예제

In[35]: pd.concat([ex_df4, ex_df5])

TypeError: categories must match existing categories when appending

 

 

 

 

 

 

 

 

 

 참고자료

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

  

 

 

 

 

 

 

반응형

댓글