파이썬(Python) 판다스(Pandas)를 활용하여 데이터를 수집하고 전처리하는 과정에서 데이터의 크고 작음을 비교하여 순서를 나열하거나 순위를 매기는 작업은 데이터 탐색의 기본입니다. 예를 들어 비즈니스 환경에서 “가장 매출이 높은 상위 10개 매장”을 선별하거나, “고객별 구매 빈도 순위”를 계산하여 등급을 부여하는 작업 등이 이에 해당합니다.
특히 빅데이터분석기사(빅분기) 실기 시험이나 현업의 데이터 분석 실무에서는 정렬과 순위 계산을 정확히 처리해야 이후 행해지는 데이터 필터링이나 파생 변수 생성 단계에서 오류를 방지할 수 있습니다. 이번 글에서는 판다스의 핵심 정렬 함수인 sort_values()와 순위 계산 함수인 rank()의 개념, 주요 파라미터, 그리고 실전 비즈니스 가상 데이터를 활용한 예제를 체계적으로 정리하겠습니다.
1. 특정 컬럼 기준 데이터 나열하기: sort_values() 함수
1.1. sort_values()의 기본 개념과 축 설정
sort_values() 함수는 하나 이상의 컬럼 값을 기준으로 데이터프레임의 행 순서를 재정렬하는 함수입니다. 기본적으로 숫자는 오름차순(작은 값에서 큰 값 순서), 문자는 사전식 순서로 정렬됩니다.
- by: 정렬 기준이 될 컬럼 이름을 문자열로 지정하거나, 여러 컬럼일 경우 리스트 형태로 지정합니다.
- ascending: 오름차순 여부를 결정하는 불리언(Boolean) 파라미터입니다. 기본값은
True(오름차순)이며,False로 지정하면 내림차순(큰 값에서 작은 값 순서)으로 정렬됩니다. - inplace:
True로 지정하면 원본 데이터프레임을 직접 변경하고,False(기본값)이면 정렬이 적용된 새로운 복사본 객체를 반환합니다.
1.2. 비즈니스 예시로 이해하는 단일 및 다중 컬럼 정렬
쇼핑몰의 고객별 주문 데이터프레임을 활용하여 정렬을 수행해 보겠습니다.
import pandas as pd
# 가상 고객 주문 데이터 생성
sales_df = pd.DataFrame({
'고객명': ['이민수', '김지아', '박준영', '최현우', '정다은'],
'거주지역': ['서울', '경기', '서울', '부산', '경기'],
'주문건수': [5, 12, 8, 5, 10],
'총구매액': [250000, 1200000, 850000, 150000, 950000]
})
이 데이터프레임에서 “총구매액이 높은 고객부터 정렬”하는 단일 컬럼 내림차순 정렬과, “거주지역별로 묶은 뒤 주문건수가 많은 순서로 정렬”하는 다중 컬럼 정렬을 구현해 보겠습니다.
# 1. 단일 컬럼 내림차순 정렬 (총구매액 기준)
top_spenders = sales_df.sort_values(by='총구매액', ascending=False)
# 2. 다중 컬럼 정렬 (지역은 오름차순, 주문건수는 내림차순)
# by와 ascending 파라미터에 각각 대응하는 리스트를 전달합니다.
multi_sorted = sales_df.sort_values(by=['거주지역', '주문건수'], ascending=[True, False])
다중 컬럼 정렬 시 ascending 파라미터에 리스트를 전달하면 각 컬럼마다 서로 다른 정렬 기준을 독립적으로 적용할 수 있어 복잡한 조건의 데이터 정렬 시 유용합니다.
2. 데이터 간의 서열 매기기: rank() 함수 완전 정복
2.1. rank() 함수의 동순위(Tie) 처리 방식
rank() 함수는 각 값의 순위를 계산하여 기본적으로 float형 순위 값을 반환합니다. 이 함수를 다룰 때 가장 주목해야 하는 부분은 값이 완전히 같은 동순위 데이터가 존재할 때의 처리 메커니즘입니다. 판다스는 method 파라미터를 통해 이를 세부적으로 제어할 수 있도록 지원합니다.
- method=’average’: 동순위 데이터들의 순위 평균값을 부여합니다. (판다스의 기본값)
- 예시: 공동 2위가 2명 있으면 둘 다 2.5위로 처리합니다. (2위와 3위의 평균)
- method=’min’: 동순위 데이터 중 가장 낮은(작은) 순위를 부여합니다. 일반적인 스포츠 순위 산정 방식과 유사합니다.
- 예시: 공동 2위가 2명 있으면 둘 다 2위로 처리하고, 다음 순위는 4위가 됩니다.
- method=’max’: 동순위 데이터 중 가장 높은(큰) 순위를 부여합니다.
- 예시: 공동 2위가 2명 있으면 둘 다 3위로 처리하고, 다음 순위는 4위가 됩니다.
- method=’first’: 데이터프레임 상에 먼저 등장한 행에 더 높은 순위를 부여합니다. 동순위 없이 고유한 순위를 만들어 줍니다.
- method=’dense’:
min방식처럼 동순위 중 최소 순위를 부여하지만, 다음 순위를 건너뛰지 않고 바로 다음 정수로 이어 붙입니다.- 예시: 공동 2위가 2명 있어도 둘 다 2위로 처리된 뒤, 다음 순위는 3위가 됩니다.
2.2. 비즈니스 예시로 보는 rank 활용
앞서 정의한 sales_df에서 ‘주문건수’ 컬럼은 ‘이민수’와 ‘최현우’ 고객이 각각 5건으로 동일한 값을 가집니다. 이들의 순위가 method 옵션에 따라 어떻게 변하는지 파생 변수를 생성하여 비교해 보겠습니다.
# 내림차순 순위를 계산하기 위해 ascending=False 지정
# 1. 기본값 (average 방식)
sales_df['순위_average'] = sales_df['주문건수'].rank(ascending=False, method='average')
# 2. 스포츠형 순위 (min 방식)
sales_df['순위_min'] = sales_df['주문건수'].rank(ascending=False, method='min')
# 3. 촘촘한 순위 (dense 방식)
sales_df['순위_dense'] = sales_df['주문건수'].rank(ascending=False, method='dense')
[출력 결과 요약]
- ‘주문건수’가 5로 공동 최하위인 두 고객의 경우:
average방식에서는 공동 4.5위로 연산됩니다.min방식에서는 공동 4위로 연산된 후 다음 순위를 건너뛰게 됩니다.dense방식에서는 공동 4위로 처리된 뒤 다음 순위를 건너뛰지 않고 연속된 순위를 부여합니다.
3. 실무 환경에서의 정렬 및 순위 연산 예외 처리
3.1. 결측치(NaN)가 포함된 데이터 정렬
데이터 수집 과정에서 누락된 결측치(NaN)가 존재할 때 정렬을 시도하면, 판다스는 기본적으로 결측치를 가장 마지막 행으로 배치합니다. 만약 분석 목적에 따라 결측치를 가장 앞으로 보내야 한다면 na_position 파라미터를 사용해 위치를 조정할 수 있습니다.
# 결측치를 정렬 결과의 가장 처음에 배치
df_na_first = sales_df.sort_values(by='총구매액', na_position='first')
3.2. 정렬 후 인덱스 불일치 현상 해결
sort_values()를 실행하면 행들의 위치가 바뀌면서 기존 인덱스 번호도 함께 뒤섞이게 됩니다. 정렬 상태를 유지한 채 인덱스를 0부터 시작하는 순차적인 정수로 초기화하고 싶다면 ignore_index=True 파라미터를 추가하거나, 정렬 후 .reset_index(drop=True)를 연결하여 사용하는 편이 구조적으로 안정적입니다.
# 정렬과 동시에 인덱스 번호를 순차적으로 재정렬
df_clean_index = sales_df.sort_values(by='총구매액', ascending=False, ignore_index=True)
4. 빅데이터분석기사 실기 시험 환경에서의 실전 활용 포인트
빅데이터분석기사 실기 시험(특히 작업형 제1유형)에서는 특정 조건으로 정렬하거나 순위를 매긴 뒤, 그 결과를 바탕으로 서브셋 데이터를 추출하여 통계량을 연산하는 문제가 자주 출제됩니다.
4.1. 상위/하위 특정 데이터의 통계량 추출
예를 들어 “총구매액을 기준으로 내림차순 정렬한 뒤, 상위 3개 행의 주문건수 평균을 구하시오”라는 문제가 출제된다면 다음과 같이 간결하게 해결할 수 있습니다.
# 1. 내림차순 정렬 및 인덱스 초기화
sorted_df = sales_df.sort_values(by='총구매액', ascending=False, ignore_index=True)
# 2. 상위 3개 행 슬라이싱 후 주문건수 컬럼의 평균 계산
result = sorted_df.loc[0:2, '주문건수'].mean()
print(result)
4.2. rank() 기반 필터링 응용
또는 “주문건수 순위(min 방식, 내림차순)가 3위 이내인 고객들의 총구매액 합계를 구하시오”라는 요건이 주어질 경우, rank() 함수로 파생 변수를 만든 뒤 앞서 7화에서 배운 불리언 인덱싱과 결합하여 정밀하게 필터링할 수 있습니다.
# 1. 순위 컬럼 생성
sales_df['주문순위'] = sales_df['주문건수'].rank(ascending=False, method='min')
# 2. 3위 이내 조건으로 필터링하여 합계 연산
final_sum = sales_df.loc[sales_df['주문순위'] <= 3, '총구매액'].sum()
print(final_sum)
이처럼 정렬과 순위 계산은 단독으로 쓰이기보다 다른 판다스 연산 함수들과 메서드 체이닝 형태로 활용하거나 다른 판다스 함수와 함께 사용하여 분석 목적에 맞는 정답을 도출하는 징검다리 역할을 하므로 숙련도를 높여두는 것이 유리합니다.
5. 요약 및 다음 화 안내
sort_values(): 특정 컬럼의 값을 기준으로 행을 재정렬하며, 다중 정렬 시 리스트를 활용합니다. 인덱스 정돈을 위해ignore_index=True옵션을 고려할 수 있습니다.rank(): 데이터 간의 순위를 계산하며, 동순위 발생 시 처리 방식에 따라method파라미터(average,min,max,first,dense)를 알맞게 선택해야 합니다.- 결측치 관리:
na_position옵션을 조절하여 결측치의 배치 순서를 제어할 수 있습니다.
다음 [판다스 10화]에서는 수집 및 정렬된 전체 데이터프레임의 대표적인 통계적 수치와 범주별 빈도수를 빠르게 요약해 주는 강력한 탐색 도구인 describe()와 value_counts() 함수로 데이터 탐색하기에 대해 상세히 학습해 보겠습니다. 데이터의 전반적인 분포를 직관적으로 파악하는 방법을 함께 정복해 봅시다.