Rangering og percentiler i grupper
Beregn rangeringer inden for grupper med groupby().rank(), og opret percentilintervaller med pd.qcut til relative sammenligninger.
Rangering og percentiler i grupper er en gratis Pandas & NumPy Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Pandas & NumPy Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Pandas & NumPy Academy-kurset indeholder 4 lektioner i alt.
Hvorfor rangordne inden for grupper?
Rå værdier er ofte mindre meningsfulde end relative rangordener. En sælger med en månedlig omsætning på $50,000 er en topperformer, hvis gennemsnittet er $30,000, men en dårlig performer, hvis gennemsnittet er $80,000. Når du beregner rangordener inden for grupper (f.eks. rang inden for hver region eller rang inden for hvert kvartal), får du en normaliseret sammenligning, der tager højde for forskellige udgangsniveauer på tværs af grupper. Pandas gør det nemt at rangordne inden for grupper med 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() — grundlæggende rangordning
Series.rank() tildeler hver værdi en rang: rang 1 er den mindste, og rang n er den største. Parameteren ascending=False vender retningen, så rang 1 er den største. Resultatet er en Series med flydende tal (ikke heltal), fordi ens værdier som standard håndteres ved at tage gennemsnittet af deres ranger. For en kolonne med 5 værdier går rangerne fra 1.0 til 5.0 — eller nogle værdier kan ved ens værdier dele en rang som 2.5.
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.5Metoder til håndtering af ens værdier i rank()
Parameteren method styrer, hvad der sker med ens værdier. Mulighederne er: 'average' (standard — ens værdier deler gennemsnittet af deres ranger), 'min' (alle ens værdier får den laveste rang), 'max' (alle får den højeste rang), 'first' (ranger efter forekomst — ingen ens ranger) og 'dense' (ingen huller i rangerne — 1, 2, 3, 3, 4 bliver til 1, 2, 3, 3, 4 i stedet for 1, 2, 3, 3, 5). Metoden 'dense' er mest nyttig til percentillignende rangordning.
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)Rangordning inden for grupper med groupby().rank()
groupby('group_col')['value_col'].rank() beregner ranger uafhængigt inden for hver gruppe. Rangen nulstilles ved begyndelsen af hver gruppe — den bedste performer i East-regionen får derfor rang 1 i East, og den bedste i West-regionen får også rang 1 i West. Det er det, der gør groupby-rangordning så nyttig til fair sammenligninger på tværs af grupper.
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))Percentilrang med rank(pct=True)
Hvis du angiver pct=True i rank(), returneres percentilrangen: en værdi mellem 0 og 1, der angiver, hvilken andel af værdierne i gruppen der er mindre end eller lig med den aktuelle værdi. En percentilrang på 0.8 betyder, at værdien ligger i 80. percentil — højere end 80 % af alle værdier. Denne normalisering gør værdier fra grupper af forskellig størrelse direkte sammenlignelige, uden at du behøver kende de faktiske gruppestørrelser.
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: Inddeling baseret på kvantiler
pd.qcut(series, q) opdeler værdier i intervaller med samme frekvens, så hvert interval indeholder omtrent det samme antal observationer. I modsætning til pd.cut, som bruger intervaller med samme bredde, tilpasser pd.qcut intervalgrænserne til dataenes fordeling. Det er perfekt til at oprette kvartiler (q=4), kvintiler (q=5) eller deciler (q=10) til præstationsniveauer.
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 sammenlignet med pd.qcut
pd.cut(series, bins=n) opretter intervaller med samme bredde (samme interval, forskelligt antal). pd.qcut(series, q=n) opretter intervaller med samme frekvens (samme antal, forskellige intervaller). For skævt fordelte data giver pd.cut næsten tomme intervaller i yderområderne, mens pd.qcut fordeler observationerne jævnt. Vælg pd.cut, når intervalgrænserne har en naturlig forretningsmæssig betydning (prisintervaller, aldersgrupper), og vælg pd.qcut til præstationsniveauer, hvor du ønsker grupper af samme størrelse.
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())Oprettelse af decilmærkater med pd.qcut
pd.qcut(series, q=10, labels=range(1,11)) tildeler hver observation dens decil (1 til 10). Det er en standardteknik i marketinganalyse (deciler for kundeværdi), kreditvurdering (risikodeciler) og AB-test (trafikdeciler til kohorteanalyse). Parameteren labels kan være en vilkårlig liste med samme længde som q — brug strenge som ['Bottom 10%', ..., 'Top 10%'] for et mere læsevenligt output.
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))Percentilintervaller inden for grupper
Kombiner groupby med pd.qcut ved hjælp af transform for at oprette percentilintervaller inden for hver gruppe. Det er nyttigt, når du vil rangordne kunder inden for hver region i stedet for globalt — en kunde i den nederste globale decil kan ligge øverst i sin regionale decil. Brug 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))Top-N inden for grupper
Et almindeligt forretningsspørgsmål er: »Hvem er de 3 bedste performere i hver region?« Brug groupby().rank(), og filtrer derefter efter rang: df[df['rank_col'] <= 3]. Det fungerer problemfrit med grupper af enhver størrelse og håndterer ens værdier på en hensigtsmæssig måde ved at beholde mere end 3 rækker, hvis der er ens ranger ved grænsen. Alternativt kan du bruge groupby().nlargest(n), som returnerer de n største værdier pr. gruppe direkte uden at tilføje en rangkolonne.
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))Kombination af rang og transformering til normalisering
Du kan bruge groupby().rank(pct=True) sammen med transform til at føje en kolonne med percentilrang til den oprindelige DataFrame. Denne normaliserede kolonne er ofte mere nyttig som modelvariabel end den rå værdi — den er uafhængig af skala og kan sammenlignes på tværs af grupper. I maskinlæring er percentilranger et enkelt alternativ til standardisering (z-score), som er mere robust over for afvigere.
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))Hurtigt tjek
Test din forståelse af rang- og percentiloperationer fra denne lektion.
Opsummering af lektionen
I denne lektion lærte du, at Series.rank() beregner numeriske ranger med konfigurerbar håndtering af ens værdier, at groupby().rank() nulstiller ranger inden for hver gruppe for at give en fair sammenligning på tværs af grupper, at pct=True omdanner ranger til percentiler (0 til 1), og at pd.qcut opretter intervaller med samme frekvens til tildeling af kvartil-, decil- og percentilniveauer. Næste gang undersøger vi tips til bedre ydeevne i Pandas — profilering, undgåelse af langsomme løkker og effektive datatyper.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Rangering og percentiler i grupper” gratis?
Ja — hele teksten til “Rangering og percentiler i grupper” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Pandas & NumPy Academy-kurset, skal du opgradere til CoddyKit PRO. Pandas & NumPy Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Rangering og percentiler i grupper”?
Beregn rangeringer inden for grupper med groupby().rank(), og opret percentilintervaller med pd.qcut til relative sammenligninger. Du øver dig i Pandas & NumPy Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Pandas & NumPy Academy?
Der kræves ingen tidligere erfaring. Pandas & NumPy Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Rangering og percentiler i grupper”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Pandas & NumPy Academy-lektion?
Ja. Alle Pandas & NumPy Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Rullende vinduer
- Udvidende vinduer
- Eksponentielt vægtet glidende gennemsnit
- Rangering og percentiler i grupper