나만의 기준으로 정렬하기
나만의 기준을 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
}

위 표는 df_target의 dataframe
(방법-1)을 사용하여 내가 원하는 순서대로 정렬을 해보겠다.
df_target = df_target.set_index("광역").reindex(sorted(province_dict, key=province_dict.get))
df_target

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

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

(예시-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)

결과는 같지만,
(예시-1)과의 차이점은 이렇게 했을 때는 “광역”열이 범주화되었고 순서도 있다는 것이다.
pd.Categorical(df_target["광역"], categories=sorted(province_dict, key=province_dict.get), ordered=True)

Categories (17, object): [‘서울특별시’ < ‘부산광역시’ < ‘대구광역시’ < ‘인천광역시’
… ‘전라남도’ < ‘경상북도’ < ‘경상남도’ < ‘제주특별자치도’] 이렇게 순서가 생겼다.
따라서, 최대·최소값을 구하면 위 순서대로 뜬다.
min(df_target["광역"]), max(df_target["광역"]), df_target["광역"].min(), df_target["광역"].max()

추가 공부사항
여기서 나는 의구심이 들었다…
눈치챘을 수도 있지만,
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()도 똑같다고 생각하면 된다.
댓글남기기