오늘 할 일: 끝내주게 숨쉬기
article thumbnail

학생들의 시험점수를 이용해 등수를 매길 때, 고객이 가장 필요로 할 것 같은 상품의 우선순위를 따질 때 등 순위를 생성해야하는 상황은 다양합니다.. 본 포스트에서는 데이터프레임에 저장된 변수를 이용해 순위를 생성하는 방법을 알아보겠습니다.

 

사용할 데이터는 다음과 같습니다.

import pandas as np
import numpy as np

sample = pd.DataFrame({'id': ['A', 'B',  'C',  'D',  'E']
                       , 'time_spend_company': [4, 3, 4, 4, 3]
                       , 'satisfaction_level': [0.89,  0.89, 0.74, 0.67, 0.72]})
display(sample)

 

1. rank 함수 이용하기

rank 함수는 주어진 값들을 이용하여 작은 값부터 1등이라고 순위를 매깁니다. 여기서는 다음 파라미터들을 자세히 알아보겠습니다.

 

  • method: 중복된 값이 있을 때 랭킹을 어떻게 매길지를 지정합니다. 예를 들어 배열 [5, 6, 6, 6, 7]에 대해 [1, 2, 3, 4, 5]라고 순위를 매긴다고 할 때, 중복된 값들의 순위를 묶어(여기에서는 [2, 3, 4]) 그룹이라고 하겠습니다.
    • average: (default) 그룹의 평균으로 순위를 부여 -> [1, 3, 3, 3, 5]
    • min: 그룹의 최솟값으로 순위를 부여 -> [1, 2, 2, 2, 5]
    • max: 그룹의 최댓값으로 순위를 부여 -> [1, 4, 4, 4, 5]
    • first: 값이 나타난 순서대로 순위를 부여 -> [1, 2, 3, 4, 5]
    • dense: ‘min’ 방법과 동일하지만, 순위가 항상 1씩 증가하도록 부여 -> [1, 2, 2, 2, 3]
  • ascending: 오름차순으로 순위 매길 것인지 여부를 정합니다. 오름차순으로 순위를 매기고 싶다면 True(default), 내림차순으로 순위를 매기고 싶다면 False라고 지정합니다

(열을 기준으로 순위를 매기거나, 결측치를 어떻게 처리할 것인지에 대한 파라미터는 아래 참고의 공식문서를 참고하세요.)

아래 코드에서는 샘플 데이터의 satisfaction_level 변수를 이용해 순위를 매긴 결과를 살펴보겠습니다.

 

먼저 method 파라미터를 변경해보았습니다. 순위를 매기는 방식으로 average, min, max, first, dense 방법을 적용한 결과는 아래와 같습니다.

sample_rank = sample[['satisfaction_level']].copy()
sample_rank['rank_average'] = sample.satisfaction_level.rank(method='average')
sample_rank['rank_min'] = sample.satisfaction_level.rank(method='min')
sample_rank['rank_max'] = sample.satisfaction_level.rank(method='max')
sample_rank['rank_first'] = sample.satisfaction_level.rank(method='first')
sample_rank['rank_dense'] = sample.satisfaction_level.rank(method='dense')

display(sample_rank)

 

다음으로 ascending 파라미터를 변경해보았습니다. 오름차순 랭킹, 내림차순 랭킹을 적용한 결과는 아래와 같습니다.

sample_rank = sample[['satisfaction_level']].copy()
sample_rank['rank_asc'] = sample.satisfaction_level.rank(method='average', ascending=True)
sample_rank['rank_desc'] = sample.satisfaction_level.rank(method='average', ascending=False)

display(sample_rank)

 

이제 두 개 변수를 이용하여 순위를 매기는 방법에 대해 알아보겠습니다.

sample_rank = sample.copy()
sample_rank['rank'] = sample[['time_spend_company', 'satisfaction_level']].apply(tuple, axis=1)\
                         .rank(method='dense', ascending=True).astype(np.int32)

display(sample_rank)

순위를 매길 때 사용할 두 개 변수를 묶어 튜플화한 후, 랭크 함수를 적용합니다. time_spend_company 변수로 먼저 순위를 매기고, 같은 값이면 satisfaction_level 변수를 그 다음으로 살펴보고 최종 순위를 매기는 식이죠. 오름차순 랭킹을 매기도록 하여 작은 값부터 순위를 가져가는 것을 확인할 수 있습니다. 

그렇다면 한 변수는 오름차순 랭킹을 매기면서 다른 변수는 내림차순 랭킹을 매기고 싶을 때는 어떻게 할까요? rank 함수의 ascending은 bool 값만 argument로 받고, list of bool 값을 받지 않아 이때는 sort_values 함수를 사용해야 합니다.

 

 

2. sort_values 함수 이용하기

두 개 이상의 변수를 사용하여 순위를 매기고 싶을 때는 sort_values 함수를 사용할 수 있습니다. 아래 코드를 통해 살펴보겠습니다.

 

cols = ['time_spend_company', 'satisfaction_level']
tups = sample[cols].sort_values(by=cols, ascending=(True, False)).apply(tuple, axis=1)
f, i = pd.factorize(tups)
display(tups, f, i)

 

순위를 매기는 데에 사용할 변수들을 cols에 지정해주고, sort_values 함수를 이용하여 정렬합니다. 첫번째 변수인 time_spend_company는 오름차순으로, 두번째 변수인 satisfaction_level은 내림차순으로 정렬하겠습니다. 정렬 후 튜플화하여 얻은 결과가 tups 입니다. 

판다스의 factorize 함수는 범주형 변수 등의 인코딩을 위해 사용하는데, 여기서는 정렬된 값들의 인덱스를 얻는 용도로 사용합니다. factorize 함수의 결과로 얻은 f는 0부터 4까지의 배열이며, 여기에 1을 더해 랭크로 사용할 것입니다.

 

factorized = pd.Series(f + 1, tups.index)
display(factorized)

 

기존 데이터프레임에 합쳐주기 위해 값은 f+1, 인덱스는 tups의 인덱스를 갖는 시리즈를 만들었습니다. 이 시리즈를 기존 데이터프레임에 새로운 변수로 할당하면 아래와 같은 결과를 얻을 수 있습니다. 이런 방식으로 두 개 변수로 오름차순과 내림차순을 모두 적용한 순위화를 진행할 수 있습니다. 

 

sample['rank'] = factorized
display(sample)

 

 

참고

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rank.html

 

pandas.DataFrame.rank — pandas 1.3.3 documentation

max_rank: setting method = 'max' the records that have the same values are ranked using the highest rank (e.g.: since ‘cat’ and ‘dog’ are both in the 2nd and 3rd position, rank 3 is assigned.)

pandas.pydata.org

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_values.html

 

pandas.DataFrame.sort_values — pandas 1.3.3 documentation

If True, the resulting axis will be labeled 0, 1, …, n - 1.

pandas.pydata.org

 

https://stackoverflow.com/questions/41974374/pandas-rank-by-multiple-columns

 

Pandas rank by multiple columns

I am trying to rank a pandas data frame based on two columns. I can rank it based on one column, but how can to rank it based on two columns? 'SaleCount', then 'TotalRevenue'? import pandas as pd ...

stackoverflow.com