[Pandas] nlargest / nsmallest / rank
Pandas nlargest, Pandas nsmallest, Pandas rank, Pandas nlargest / rank, Top-N pandas
정의
nlargest(n, cols): 상위 N 개 행 (sort_values + head보다 빠름)nsmallest(n, cols): 하위 N 개 행rank(): 각 원소의 순위 (1, 2, 3, …)
nlargest / nsmallest
df.nlargest(5, 'salary')
df.nsmallest(3, 'age')
df.nlargest(5, ['salary', 'age']) # 다중 키 (salary 우선, 동률 시 age)
python
import pandas as pd
df = pd.DataFrame({
'name': ['A','B','C','D','E','F'],
'score': [88, 92, 75, 92, 95, 81],
})
print(df.nlargest(3, 'score')) 결과
name score
4 E 95
1 B 92
3 D 92| name | score | |
|---|---|---|
| 4 | E | 95 |
| 1 | B | 92 |
| 3 | D | 92 |
keep 옵션
df.nlargest(3, 'score', keep='first') # 동률 시 먼저 등장 우선 (기본)
df.nlargest(3, 'score', keep='last') # 나중 등장 우선
df.nlargest(3, 'score', keep='all') # 동률 모두 포함 (3 개 초과 가능)
왜 sort + head 보다 빠른가
nlargest 는 N 크기의 힙으로 부분 정렬, O(n log k). 전체 정렬은 O(n log n).
- n = 1,000,000, k = 10 일 때 차이 큼
rank
각 원소에 순위를 매긴다.
df['rank'] = df['score'].rank(ascending=False)
python
import pandas as pd
s = pd.Series([88, 92, 75, 92, 95])
print(s.rank(method='min')) # 동률은 가장 작은 순위
print(s.rank(method='dense')) # 동률은 같은 순위, 다음은 +1
print(s.rank(method='average')) # 동률은 평균
print(s.rank(ascending=False).tolist()) # 내림차순 (큰 값이 1) 결과
0 2.0
1 3.0
2 1.0
3 3.0
4 5.0
dtype: float64
0 2.0
1 3.0
2 1.0
3 3.0
4 4.0
dtype: float64
0 2.0
1 3.5
2 1.0
3 3.5
4 5.0
dtype: float64
[4.0, 2.5, 5.0, 2.5, 1.0]method 옵션 비교
| method | 92, 92 인 경우 다음 순위 |
|---|---|
min (기본은 average) | 92, 92 모두 3 → 다음은 5 |
max | 92, 92 모두 4 → 다음은 5 |
dense | 92, 92 모두 3 → 다음은 4 |
average | 92, 92 모두 3.5 → 다음은 5 |
first | 등장 순 (92→3, 92→4) → 다음은 5 |
그룹별 순위 (SQL 의 ROW_NUMBER OVER PARTITION BY)
df['rank_in_dept'] = df.groupby('dept')['salary'].rank(ascending=False)
Pandas groupby + rank.
분위수
df['quartile'] = pd.qcut(df['score'], 4, labels=['Q1','Q2','Q3','Q4'])
df['percentile'] = df['score'].rank(pct=True)
자주 만나는 함정
1. rank 의 기본 method
rank() 의 기본은 'average', 동률을 평균값으로 둔다. 정수 순위를 원하면 method='min' 또는 'dense'.
2. NaN 처리
s.rank(na_option='keep') # NaN 은 NaN (기본)
s.rank(na_option='top') # NaN 을 가장 낮은 순위
s.rank(na_option='bottom') # NaN 을 가장 높은 순위
3. nlargest 의 다중 키
df.nlargest(3, ['a', 'b'])
# 'a' 가 더 우선, 'b' 는 동률일 때만 결정
💬 댓글