Rang en percentiel binnen groepen
Bereken rangen binnen groepen met groupby().rank() en maak percentielklassen met pd.qcut voor relatieve vergelijkingen.
Rang en percentiel binnen groepen is een gratis Pandas & NumPy Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Pandas & NumPy Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.
Waarom rangschikken binnen groepen?
Ruwe waarden zijn vaak minder betekenisvol dan relatieve rangschikkingen. Een verkoper met een maandelijkse omzet van $50,000 is een toppresteerder als het gemiddelde $30,000 is, maar een zwakke presteerder als het gemiddelde $80,000 is. Door rangen binnen groepen te berekenen (bijvoorbeeld binnen elke regio of elk kwartaal), krijg je een genormaliseerde vergelijking die rekening houdt met verschillende uitgangsniveaus tussen groepen. Met Pandas is rangschikken binnen groepen eenvoudig met groupby().rank().
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'rep': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve',
'Frank', 'Grace', 'Hank', 'Iris', 'Jake'],
'region': ['East']*5 + ['West']*5,
'sales': np.random.randint(30000, 100000, 10)
})
print(df.sort_values('region'))Series.rank() — Basisrangschikking
Series.rank() wijst aan elke waarde een rang toe: rang 1 is de kleinste waarde en rang n de grootste. De parameter ascending=False keert de richting om, zodat rang 1 de grootste waarde is. Het resultaat is een float Series (geen integer), omdat gelijke waarden standaard worden opgelost door het gemiddelde van hun rangen te nemen. Voor een kolom met 5 waarden lopen de rangen van 1.0 tot 5.0 — bij gelijke waarden kunnen sommige waarden bijvoorbeeld dezelfde rang 2.5 krijgen.
import pandas as pd
s = pd.Series([80, 45, 90, 45, 70])
print('Values:', s.values)
print('Rank (ascending=True, default):', s.rank().values)
print('Rank (ascending=False — best=1):', s.rank(ascending=False).values)
# Note: two 45s share ranks 1 and 2 → both get 1.5Methoden voor het oplossen van gelijke rangen in rank()
De parameter method bepaalt wat er met gelijke waarden gebeurt. Opties zijn: 'average' (standaard — gelijke waarden delen het gemiddelde van hun rangen), 'min' (alle gelijke waarden krijgen de laagste rang), 'max' (alle krijgen de hoogste rang), 'first' (rangen in volgorde van voorkomen — geen gelijke rangen) en 'dense' (geen gaten in de rangen — 1, 2, 3, 3, 4 wordt 1, 2, 3, 3, 4 in plaats van 1, 2, 3, 3, 5). De methode 'dense' is het handigst voor rangschikkingen in percentielstijl.
import pandas as pd
s = pd.Series([80, 45, 90, 45, 70])
result = pd.DataFrame({
'value': s,
'average': s.rank(method='average'),
'min': s.rank(method='min'),
'max': s.rank(method='max'),
'first': s.rank(method='first'),
'dense': s.rank(method='dense')
})
print(result)Rangschikken binnen groepen met groupby().rank()
groupby('group_col')['value_col'].rank() berekent rangen onafhankelijk binnen elke groep. De rang begint bij elke groep opnieuw — de beste presteerder in de regio East krijgt dus rang 1 in East, en de beste in de regio West krijgt ook rang 1 in West. Daardoor is rangschikken met groupby zo nuttig voor eerlijke vergelijkingen tussen groepen.
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'rep': list('ABCDEABCDE'),
'region': ['East']*5 + ['West']*5,
'sales': np.random.randint(30000, 100000, 10)
})
# Rank within each region (best = rank 1)
df['rank_in_region'] = df.groupby('region')['sales'].rank(ascending=False, method='min')
df_sorted = df.sort_values(['region', 'rank_in_region'])
print(df_sorted.to_string(index=False))Rangschikken op percentiel met rank(pct=True)
Als je pct=True instelt in rank(), geeft dit de percentielrang terug: een waarde tussen 0 en 1 die aangeeft welk deel van de waarden in de groep gelijk is aan of lager is dan de huidige waarde. Een percentielrang van 0.8 betekent dat de waarde op het 80e percentiel ligt — hoger dan 80% van alle waarden. Door deze normalisatie kun je waarden uit groepen van verschillende grootte rechtstreeks vergelijken zonder de werkelijke groepsgrootte te kennen.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'name': list('ABCDEFGHIJ'),
'region': ['East']*5 + ['West']*5,
'score': np.random.randint(50, 100, 10)
})
# Percentile rank within region
df['pct_rank'] = df.groupby('region')['score'].rank(pct=True)
df['percentile'] = (df['pct_rank'] * 100).round(0).astype(int)
print(df.sort_values(['region', 'percentile'], ascending=[True, False]).to_string(index=False))pd.qcut: indeling op basis van kwantielen
pd.qcut(series, q) verdeelt waarden over q intervallen met gelijke frequentie, zodat elk interval ongeveer evenveel waarnemingen bevat. In tegenstelling tot pd.cut, dat intervallen met gelijke breedte gebruikt, past pd.qcut de grenzen van de intervallen aan de verdeling van de gegevens aan. Dit is ideaal voor het maken van kwartielen (q=4), kwintielen (q=5) of decielen (q=10) voor prestatieniveaus.
import pandas as pd
import numpy as np
np.random.seed(42)
sales = pd.Series(np.random.exponential(scale=50000, size=100))
# Divide into quartiles
quartiles = pd.qcut(sales, q=4, labels=['Q1', 'Q2', 'Q3', 'Q4'])
result = pd.DataFrame({'sales': sales, 'quartile': quartiles})
print('Quartile counts (should be ~25 each):')
print(result['quartile'].value_counts().sort_index())
print('\nMean sales per quartile:')
print(result.groupby('quartile')['sales'].mean().round(0))pd.cut versus pd.qcut
pd.cut(series, bins=n) maakt intervallen met gelijke breedte (hetzelfde bereik, verschillende aantallen). pd.qcut(series, q=n) maakt intervallen met gelijke frequentie (hetzelfde aantal, verschillende bereiken). Bij scheef verdeelde gegevens ontstaan met pd.cut vrijwel lege intervallen aan de uiteinden, terwijl pd.qcut de waarnemingen gelijkmatig verdeelt. Kies pd.cut wanneer de grenzen van de intervallen een natuurlijke betekenis hebben voor de bedrijfsvoering (prijsklassen, leeftijdsgroepen); kies pd.qcut voor prestatieniveaus waarbij je groepen van gelijke grootte wilt.
import pandas as pd
import numpy as np
np.random.seed(0)
# Right-skewed data
data = pd.Series(np.random.exponential(1, 100))
cut_result = pd.cut(data, bins=5).value_counts().sort_index()
qcut_result = pd.qcut(data, q=5).value_counts().sort_index()
print('Equal-width bins (pd.cut) — uneven counts:')
print(cut_result.to_string())
print('\nEqual-frequency bins (pd.qcut) — even counts:')
print(qcut_result.to_string())Deciellabels maken met pd.qcut
pd.qcut(series, q=10, labels=range(1,11)) wijst elke waarneming toe aan het bijbehorende deciel (1 tot en met 10). Dit is een standaardtechniek in marketinganalyse (decielen van klantwaarde), kredietbeoordeling (risicodecielen) en A/B-testen (verkeersdecielen voor cohortanalyse). De parameter labels kan elke lijst zijn met dezelfde lengte als q — gebruik voor beter leesbare uitvoer tekenreeksen zoals ['Bottom 10%', ..., 'Top 10%'].
import pandas as pd
import numpy as np
np.random.seed(7)
customer_value = pd.Series(np.random.exponential(500, 1000))
# Assign to deciles 1-10
decile_labels = [f'D{i}' for i in range(1, 11)]
customer_decile = pd.qcut(
customer_value,
q=10,
labels=decile_labels
)
result = pd.DataFrame({'value': customer_value, 'decile': customer_decile})
print('Mean customer value per decile:')
print(result.groupby('decile')['value'].mean().round(0))Percentielintervallen binnen groepen
Combineer groupby met pd.qcut en gebruik transform om percentielintervallen binnen elke groep te maken. Dit is nuttig wanneer je klanten binnen elke regio wilt rangschikken in plaats van wereldwijd — een klant in het onderste wereldwijde deciel kan bovenaan het deciel van zijn of haar regio staan. Gebruik groupby('group')['value'].transform(lambda x: pd.qcut(x, q=4, labels=['Q1','Q2','Q3','Q4'])).
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'customer': range(20),
'region': ['North']*10 + ['South']*10,
'spend': np.random.randint(100, 1000, 20)
})
# Quartile within each region
def quartile_label(x):
return pd.qcut(x, q=4, labels=['Q1','Q2','Q3','Q4'])
df['region_quartile'] = df.groupby('region')['spend'].transform(quartile_label)
print(df.sort_values(['region', 'region_quartile']).to_string(index=False))De top N binnen groepen
Een veelvoorkomende bedrijfsvraag is: 'wie zijn de 3 beste presteerders in elke regio?' Gebruik groupby().rank() en filter vervolgens op rang: df[df['rank_col'] <= 3]. Dit werkt netjes voor groepen van elke grootte en gaat goed om met gelijke waarden door meer dan 3 rijen te behouden als er gelijke rangen op de grens staan. Je kunt ook groupby().nlargest(n) gebruiken. Dit geeft rechtstreeks de n grootste waarden per groep terug zonder een rangkolom toe te voegen.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'rep': [f'Rep_{i}' for i in range(15)],
'region': ['East']*5 + ['West']*5 + ['North']*5,
'revenue': np.random.randint(40000, 120000, 15)
})
df['region_rank'] = df.groupby('region')['revenue'].rank(ascending=False, method='min')
print('Top 2 per region:')
top2 = df[df['region_rank'] <= 2].sort_values(['region', 'region_rank'])
print(top2[['rep', 'region', 'revenue', 'region_rank']].to_string(index=False))Rangschikking en transform combineren voor normalisatie
Je kunt groupby().rank(pct=True) combineren met transform om een kolom met percentielrangen aan het oorspronkelijke DataFrame toe te voegen. Deze genormaliseerde kolom is vaak bruikbaarder als modelkenmerk dan de ruwe waarde — de kolom is schaalvrij en vergelijkbaar tussen groepen. Voor machinaal leren zijn percentielrangen een eenvoudig alternatief voor standaardisatie (z-scores) dat robuuster is voor uitschieters.
import pandas as pd
import numpy as np
np.random.seed(1)
df = pd.DataFrame({
'product': np.random.choice(['A', 'B', 'C'], 30),
'score': np.random.randint(50, 100, 30)
})
# Percentile rank within each product group
df['global_pct'] = df['score'].rank(pct=True).round(3)
df['group_pct'] = df.groupby('product')['score'].rank(pct=True).round(3)
print(df.sort_values(['product', 'score']).head(12).to_string(index=False))Korte controle
Test je begrip van rang- en percentielbewerkingen uit deze les.
Samenvatting van de les
In deze les heb je geleerd dat Series.rank() numerieke rangen berekent met instelbare methoden voor gelijke waarden, dat groupby().rank() de rangen binnen elke groep opnieuw laat beginnen voor een eerlijke vergelijking tussen groepen, dat pct=True rangen omzet in percentielen (0 tot 1) en dat pd.qcut intervallen met gelijke frequentie maakt voor het toewijzen van kwartiel-, deciel- en percentielniveaus. Hierna bekijken we tips voor betere prestaties in Pandas — profileren, trage lussen vermijden en efficiënte gegevenstypen gebruiken.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “Rang en percentiel binnen groepen” gratis?
Ja — de volledige tekst van “Rang en percentiel binnen groepen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Pandas & NumPy Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.
Wat leer ik in “Rang en percentiel binnen groepen”?
Bereken rangen binnen groepen met groupby().rank() en maak percentielklassen met pd.qcut voor relatieve vergelijkingen. Je oefent met Pandas & NumPy Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Pandas & NumPy Academy te beginnen?
Ervaring vooraf is niet nodig. Pandas & NumPy Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Rang en percentiel binnen groepen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Pandas & NumPy Academy?
Ja. Elke les over Pandas & NumPy Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Rollende vensters
- Expanderende vensters
- Exponentieel gewogen voortschrijdend gemiddelde
- Rang en percentiel binnen groepen