Sorting and Ranking
Rank Values
Assign a rank to each value in a column — the largest gets rank 1. By hand,
each value's rank is 1 plus the count of values strictly greater than it.
With pandas, Series.rank(ascending=False) does this in one call.
By hand
For each score, count how many other scores are strictly greater than it — that count plus 1 is the rank. All values are distinct, so there are no ties and the formula produces gap-free integer ranks.
naive.py
Replay: real traced execution (multi-file project)
scores = [80, 55, 90, 70]
ranks = []
for s in scores:
rank = 1
for other in scores:
if other > s:
rank += 1
ranks.append(rank)
print('RESULT:', ranks)
scores ← [80, 55, 90, 70]
1scores = [80, 55, 90, 70]2ranks = []values this step[80, 55, 90, 70]scoresranks ← []
1scores = [80, 55, 90, 70]2ranks = []3for s in scores:values this step[]rankss ← 80
2ranks = []3for s in scores:4 rank = 1values this step80srank ← 1
3for s in scores:4 rank = 15 for other in scores:values this step1rankother ← 80
pass 1 of 34rank = 15for other in scores:6 if other > s:7 rank += 1values this step80otherAll 3 passes — pass 1 is the card above pass other1 80 2 80 → 55 3 55 → 90 rank ← 2
6 if other > s:7 rank += 18ranks.append(rank)values this step1 → 2rankother ← 70
4rank = 15for other in scores:6 if other > s:values this step90 → 70otherif other > s:
5for other in scores:6 if other > s:7 rank += 1for other in scores:
4rank = 15for other in scores:6 if other > s:ranks ← [2]
7 rank += 18 ranks.append(rank)9print('RESULT:', ranks)values this step[] → [2]rankss ← 55
2ranks = []3for s in scores:4 rank = 1values this step80 → 55srank ← 1
3for s in scores:4 rank = 15 for other in scores:values this step2 → 1rankother ← 55, rank ← 2
pass 1 of 24rank = 15for other in scores:6 if other > s:7 rank += 18ranks.append(rank)values this step80 → 55other1 → 2rankother ← 70, rank ← 3
pass 2 of 24rank = 15for other in scores:6 if other > s:7 rank += 18ranks.append(rank)values this step90 → 70other2 → 3rankrank ← 4
6 if other > s:7 rank += 18ranks.append(rank)values this step3 → 4rankfor other in scores:
4rank = 15for other in scores:6 if other > s:ranks ← [2, 4]
7 rank += 18 ranks.append(rank)9print('RESULT:', ranks)values this step[2] → [2, 4]rankss ← 90
2ranks = []3for s in scores:4 rank = 1values this step55 → 90srank ← 1
3for s in scores:4 rank = 15 for other in scores:values this step4 → 1rankother ← 80
pass 1 of 44rank = 15for other in scores:6 if other > s:7 rank += 1values this step70 → 80otherAll 4 passes — pass 1 is the card above pass other1 70 → 80 2 80 → 55 3 55 → 90 4 90 → 70 for other in scores:
4rank = 15for other in scores:6 if other > s:ranks ← [2, 4, 1]
7 rank += 18 ranks.append(rank)9print('RESULT:', ranks)values this step[2, 4] → [2, 4, 1]rankss ← 70
2ranks = []3for s in scores:4 rank = 1values this step90 → 70srank = 1
3for s in scores:4 rank = 15 for other in scores:other ← 55, rank ← 2
pass 1 of 24rank = 15for other in scores:6 if other > s:7 rank += 18ranks.append(rank)values this step80 → 55other1 → 2rankother ← 70, rank ← 3
pass 2 of 24rank = 15for other in scores:6 if other > s:7 rank += 18ranks.append(rank)values this step90 → 70other2 → 3rankfor other in scores:
4rank = 15for other in scores:6 if other > s:ranks ← [2, 4, 1, 3]
7 rank += 18 ranks.append(rank)9print('RESULT:', ranks)values this step[2, 4, 1] → [2, 4, 1, 3]ranksfor s in scores:
2ranks = []3for s in scores:4 rank = 1stdout ← RESULT: [2, 4, 1, 3]
8 ranks.append(rank)9print('RESULT:', ranks)values this stepRESULT: [2, 4, 1, 3]stdout
With pandas
df['score'].rank(ascending=False) assigns rank 1 to the largest value.
rank() always returns float64; with distinct values the fractional part
is always .0, so casting to int is safe.
library.py
import pandas as pd
from dalib.display import set_display
set_display()
scores = [80, 55, 90, 70]
df = pd.DataFrame({'score': scores})
r = df['score'].rank(ascending=False)
ranks = [int(x) for x in r.tolist()]
print('index:', r.index.tolist())
print('values:', r.tolist())
print('dtype:', r.dtype)
print('RESULT:', ranks)
index: [0, 1, 2, 3]
values: [2.0, 4.0, 1.0, 3.0]
dtype: float64
RESULT: [2, 4, 1, 3]
Implementation notes
rank(ascending=True)(the default) assigns rank 1 to the smallest value. Passascending=Falseto rank largest-first, as done here — this matches the naive formula (1 + count of values greater).- With distinct values all tie methods agree. When ties exist, pandas offers:
method='average'(default — mean of tied ranks),method='min'(lowest rank in the tie group),method='dense'(no gaps —[1,2,2,3]rather than[1,2,2,4]). rank()always returnsfloat64regardless of the input dtype; cast withint()or.astype(int)only after confirming no NaN values.- Cross-reference:
rank-assign(python-data-basics) for the pure-Python version.