Percentiles and Spread
Percentile Rank
A percentile rank answers: what percentage of the data falls at or below a
given value? Definition used here: rank = (count of values ≤ target) / n ×
100 — the "weak" definition. Loop over values, count those ≤ target, divide
by n and scale to 100. With scipy, percentileofscore(x, target, kind='weak') uses the same ≤ rule. Values: [2,4,...,20] n=10, target=12 →
6 values ≤ 12 → rank=60.0.
By hand
Definition: rank = (count of values ≤ target) / n × 100 (kind='weak').
Loop over values; increment count when v <= target. With target=12 and
n=10, six values qualify (2,4,6,8,10,12) → rank = 6/10 × 100 = 60.0.
values = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
target = 12
n = len(values)
count = 0
for v in values:
if v <= target:
count = count + 1
rank = count / n * 100
print('RESULT:', round(rank, 2))
values ← [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
1values = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]2target = 12values this step[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]valuestarget ← 12
1values = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]2target = 123n = len(values)values this step12targetn ← 10
2target = 123n = len(values)4count = 0values this step10ncount ← 0
3n = len(values)4count = 05for v in values:values this step0countv ← 2, count ← 1
pass 1 of 64count = 05for v in values:6 if v <= target:7 count = count + 18rank = count / n * 100values this step2v0 → 1countAll 6 passes — pass 1 is the card above pass vcount1 2 0 → 1 2 2 → 4 1 → 2 3 4 → 6 2 → 3 4 6 → 8 3 → 4 5 8 → 10 4 → 5 6 10 → 12 5 → 6 v ← 14
pass 1 of 44count = 05for v in values:6 if v <= target:7 count = count + 1values this step12 → 14vAll 4 passes — pass 1 is the card above pass v1 12 → 14 2 14 → 16 3 16 → 18 4 18 → 20 for v in values:
4count = 05for v in values:6 if v <= target:rank ← 60.0
7 count = count + 18rank = count / n * 1009print('RESULT:', round(rank, 2))values this step60.0rankstdout ← RESULT: 60.0
8rank = count / n * 1009print('RESULT:', round(rank, 2))values this stepRESULT: 60.0stdout
With the library
scipy.stats.percentileofscore(x, target, kind='weak') counts values ≤
target and scales to 100 — identical to the naive formula. kind='strict'
counts strictly < target; kind='mean' averages the two. Always specify
kind explicitly to avoid ambiguity.
from scipy.stats import percentileofscore
from dalib.display import set_display
set_display()
values = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
target = 12
rank = percentileofscore(values, target, kind='weak')
print('target:', target)
print('n:', len(values))
print('RESULT:', round(rank, 2))
target: 12
n: 10
RESULT: 60.0
Implementation notes
kind='weak'(≤) is the most common definition and matches the intuition "12 is at the 60th percentile."kind='strict'(<) gives 50.0 here (five values below 12);kind='mean'gives 55.0.- Percentile rank is the inverse of
np.percentile: given a rank, percentile gives the value; given a value, percentile rank gives the rank. - Cross-reference:
five-number-summary(this chapter) for the fixed landmarks (0, 25, 50, 75, 100th percentiles) of a distribution.