본문으로 건너뛰기
김신건의 로그

[Pandas] nlargest / nsmallest / rank

· 수정 · 📖 약 1분 · 258자/단어 #python #pandas #sorting #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
namescore
4E95
1B92
3D92

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 옵션 비교

method92, 92 인 경우 다음 순위
min (기본은 average)92, 92 모두 3 → 다음은 5
max92, 92 모두 4 → 다음은 5
dense92, 92 모두 3 → 다음은 4
average92, 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' 는 동률일 때만 결정

참고

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기