나만의 기준을 dictionary 형태로 저장 후 .reindex(sorted())pd.Categorical()
이용하여 나만의 기준으로 정렬하는 법을 공부

공부하게 된 이유

데이터를 정렬하는 방법에는 다양한 방법이 있다.

흔히 알고 있는 sort_values(), sort_index() 등이 있지만
기준을 정해주지 않는 한 사전 순으로 정렬한다.

따라서, 내가 중요하다고 생각하는 변수들의 순서를 매기고 그 순서에 맞게 정렬
하고 싶었기에 공부하게 되었다.

즉, 내가 나만의 기준을 정하고 그것에 맞게 정렬하고 싶었다.


사용 방법

방법-1

data.set_index("column_name").reindex(sorted(dictionary, key=dictionary.get))
  • dictionary : 내가 원하는 기준으로 만든 dictionary 자료

방법-2

pd.Categorical(data, categories=None, ordered=False) # defalut값을 기준으로 작성
  • data : 범주형 데이터로 변환할 데이터 (series 형태)
  • categories : 카테고리 리스트, 0~N번까지의 리스트가 있을때 index가 작은 것이 우선 순위로 생각
  • ordered : categories에서 범주화한 데이터에 순서를 줄꺼냐 안줄꺼냐


예시

(예시-1)

# pandas 불러오기
import pandas as pd

# 우선 순위를 dictionary 형태로 지정 (내가 원하는 기준)
province_dict = {
    '서울특별시': 0,
    '부산광역시': 1,
    '대구광역시': 2,
    '인천광역시': 3,
    '광주광역시': 4,
    '대전광역시': 5,
    '울산광역시': 6,
    '세종특별자치시': 7,
    '경기도': 8,
    '강원도': 9,
    '충청북도': 10,
    '충청남도': 11,
    '전라북도': 12,
    '전라남도': 13,
    '경상북도': 14,
    '경상남도': 15,
    '제주특별자치도': 16
}

image-20240520152849787

위 표는 df_target의 dataframe


(방법-1)을 사용하여 내가 원하는 순서대로 정렬을 해보겠다.

df_target = df_target.set_index("광역").reindex(sorted(province_dict, key=province_dict.get))
df_target

image-20240520135615222

만약, “광역”열이 index에 들어가 있는게 싫다면 reset_index를 통해 풀어주면 된다.

df_target.reset_index(inplace=True)
df_target

image-20240520140053473

당장의 순서만 바꿔준 것일 뿐,
범주화하여 순서를 부여한 것이 아니기 때문에 최대·최소를 구하면 사전 순으로 나온다.

min(df_target["광역"]), max(df_target["광역"]), df_target["광역"].min(), df_target["광역"].max()

image-20240520140604334


(예시-2)

앞으로도 이 순서를 유지하고 싶으면 어떻게 해야할까?
“광역” 열을 범주형으로 만들고 순서를 지정해주면 된다.

방법-2를 사용하여 내가 원하는 순서대로 정렬을 해보겠다.
(예시-1의 province_dict 그대로 사용)

# pd.Categorical()함수 사용
df_target["광역"] = pd.Categorical(df_target["광역"], categories=sorted(province_dict, key=province_dict.get), ordered=True)

# 정렬
df_target_4.sort_values(by="광역", ascending=True)

image-20240520140053473


결과는 같지만,
(예시-1)과의 차이점은 이렇게 했을 때는 “광역”열이 범주화되었고 순서도 있다는 것이다.

pd.Categorical(df_target["광역"], categories=sorted(province_dict, key=province_dict.get), ordered=True)

image-20240520141957586

Categories (17, object): [‘서울특별시’ < ‘부산광역시’ < ‘대구광역시’ < ‘인천광역시’
… ‘전라남도’ < ‘경상북도’ < ‘경상남도’ < ‘제주특별자치도’] 이렇게 순서가 생겼다.


따라서, 최대·최소값을 구하면 위 순서대로 뜬다.

min(df_target["광역"]), max(df_target["광역"]), df_target["광역"].min(), df_target["광역"].max()

image-20240520150413651


추가 공부사항

여기서 나는 의구심이 들었다…
눈치챘을 수도 있지만,
min(df_target[“광역”])와 df_target[“광역”].min()의 결과값이 다르다.

처음에 범주형에 순서를 부여하면 최대·최소도 그에 맞게 변한다고 알고 있었고
구글링을 했을 때도 그렇다고 하는데,,,

순서를 주고 min(df_target[“광역”]) 했을 때 계속 ‘경기도’가 출력이 되어 뭐지? 했었다.


결과를 말하기 전 아래와 같이 명시할 것이라는 것을 참고하자.

함수 설명
min(df_target[“광역”]) 파이썬 내장 min()
df_target[“광역”].min() 판다스 min()


“파이썬 내장 min()”과 “판다스 min()”은 내부적으로 작동하는 방식에 차이가 있다고 한다.
이번 공부와 관련되어서 말하면,

함수 동작 방식 범주형 데이터일 경우 범주형 데이터가 아닐 경우
파이썬 내장 min() 시리즈의 각 값을 반복하면서
가장 작은 값을 찾음
사전순 정렬 사전순 정렬
판다스 min() 판다스 내부 최적화를 사용하여
최소값을 계산
(순서가 부여된 경우)
정의된 범주 순서에 따라 최소값 반환
(순서가 부여되지 않은 경우)
오류 발생
사전순 정렬

순서가 부여된 경우는 “ordered = True”
순서가 부여되지 않은 경우는 “ordered = False”


이러한 특징이 있기 때문에,

min(df_target["광역"]), max(df_target["광역"]), df_target["광역"].min(), df_target["광역"].max()

위 코드의 최대·최소 값이 다르게 출력된 것이다.

또한, min()뿐만 아니라 max()도 똑같다고 생각하면 된다.

댓글남기기