Pandas & NumPy Academy · Lektion

Rang och percentil inom grupper

Beräkna rang inom grupper med groupby().rank() och skapa percentilgrupper med pd.qcut för relativa jämförelser.

Lektion 4 av 413 steg

Rang och percentil inom grupper är en gratis lektion i Pandas & NumPy Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Pandas & NumPy Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Pandas & NumPy Academy innehåller totalt 4 lektioner.

Varför rangordna inom grupper?

Råvärden är ofta mindre meningsfulla än relativa rangordningar. En säljare med 50 000 dollar i månadsintäkter presterar mycket bra om genomsnittet är 30 000 dollar, men dåligt om genomsnittet är 80 000 dollar. Genom att beräkna rangordningar inom grupper (till exempel inom varje region eller kvartal) får ni en normaliserad jämförelse som tar hänsyn till olika utgångsnivåer mellan grupper. Pandas gör det enkelt att rangordna inom 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äggande rangordning

Series.rank() tilldelar varje värde en rang: rang 1 är det minsta värdet och rang n det största. Parametern ascending=False vänder på riktningen så att rang 1 är det största värdet. Resultatet är en float-Series, inte en heltals-Series, eftersom lika värden som standard hanteras genom att deras rangvärden beräknas som ett medelvärde. För en kolumn med 5 värden sträcker sig rangvärdena från 1.0 till 5.0 – eller, vid lika värden, kan vissa värden dela på 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.5

Metoder för att hantera lika rangvärden i rank()

Parametern method styr vad som händer med lika värden. Alternativen är: 'average' (standard – lika värden delar på medelvärdet av deras rangvärden), 'min' (alla lika värden får den lägsta rangen), 'max' (alla får den högsta rangen), 'first' (rangordnas efter förekomstordning – inga lika rangvärden) och 'dense' (inga luckor i rangordningen – 1, 2, 3, 3, 4 blir 1, 2, 3, 3, 4 i stället för 1, 2, 3, 3, 5). Metoden 'dense' är mest användbar för percentilliknande rangordningar.

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 inom grupper med groupby().rank()

groupby('group_col')['value_col'].rank() beräknar rangordningar oberoende inom varje grupp. Rangordningen börjar om i varje grupp – den bästa medarbetaren i region Öst får alltså rang 1 i Öst, och den bästa i region Väst får också rang 1 i Väst. Det är detta som gör groupby-rangordning så användbar för rättvisa jämförelser mellan 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))

Percentilrangordning med rank(pct=True)

Om ni anger pct=True i rank() returneras percentilrangen: ett värde mellan 0 och 1 som anger hur stor andel av värdena i gruppen som är mindre än eller lika med det aktuella värdet. En percentilrang på 0.8 betyder att värdet ligger i den 80:e percentilen – det är högre än 80 % av alla värden. Denna normalisering gör värden från grupper av olika storlek direkt jämförbara utan att ni behöver känna till gruppernas faktiska storlek.

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: indelning baserad på kvantiler

pd.qcut(series, q) delar in värden i q frekvensmässigt lika intervall, så att varje intervall innehåller ungefär lika många observationer. Till skillnad från pd.cut, som använder intervall med samma bredd, anpassar pd.qcut intervallgränserna efter datans fördelning. Det passar utmärkt för att skapa kvartiler (q=4), kvintiler (q=5) eller deciler (q=10) för prestationsnivåer.

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 jämfört med pd.qcut

pd.cut(series, bins=n) skapar intervall med samma bredd (samma intervallbredd, olika antal värden). pd.qcut(series, q=n) skapar intervall med samma frekvens (samma antal värden, olika intervallbredder). För snedfördelade data blir intervallen i ytterkanterna vid användning av pd.cut nästan tomma, medan pd.qcut fördelar observationerna jämnt. Välj pd.cut när intervallgränserna har en naturlig affärsmässig betydelse (prisintervall, åldersgrupper), och pd.qcut för prestationsnivåer där ni vill ha grupper av samma storlek.

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())

Skapa deciletiketter med pd.qcut

pd.qcut(series, q=10, labels=range(1,11)) tilldelar varje observation en decil (1 till 10). Detta är en standardmetod inom marknadsanalys (decilindelning efter kundvärde), kreditbedömning (riskdeciler) och A/B-testning (trafikdeciler för kohortanalys). Parametern labels kan vara vilken lista som helst med samma längd som q – använd strängar som ['Bottom 10%', ..., 'Top 10%'] för ett mer lättläst resultat.

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))

Percentilintervall inom grupper

Kombinera groupby med pd.qcut genom att använda transform för att skapa percentilintervall inom varje grupp. Det är användbart när ni vill rangordna kunder inom varje region i stället för globalt – en kund i den nedersta globala decilen kan ligga högst i sin regionala decil. Använd 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))

Topp N inom grupper

En vanlig affärsfråga är ”vilka är de tre bästa medarbetarna i varje region?” Använd groupby().rank() och filtrera sedan efter rang: df[df['rank_col'] <= 3]. Detta fungerar smidigt oavsett gruppstorlek och hanterar lika rangvärden på ett bra sätt genom att behålla fler än tre rader om flera värden delar på rangen vid gränsen. Alternativt kan ni använda groupby().nlargest(n), som direkt returnerar de n största värdena per grupp utan att lägga till en rangkolumn.

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))

Kombinera rangordning och transformering för normalisering

Ni kan använda groupby().rank(pct=True) tillsammans med transform för att lägga till en kolumn med percentilrang i den ursprungliga DataFrame-strukturen. Denna normaliserade kolumn är ofta mer användbar som modellvariabel än råvärdet – den är skaloberoende och jämförbar mellan grupper. Inom maskininlärning är percentilranger ett enkelt alternativ till standardisering (z-värden) som är mer robust mot extremvärden.

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))

Snabb kontroll

Testa era kunskaper om rang- och percentiloperationer från den här lektionen.

Sammanfattning av lektionen

I den här lektionen har ni lärt er att Series.rank() beräknar numeriska rangvärden med konfigurerbar hantering av lika värden, att groupby().rank() börjar om rangordningen inom varje grupp för rättvisa jämförelser mellan grupper, att pct=True omvandlar rangvärden till percentiler (0 till 1) och att pd.qcut skapar frekvensmässigt lika intervall för tilldelning av kvartil-, decil- och percentilnivåer. Nästa steg är att utforska prestandatips för Pandas – profilering, att undvika långsamma loopar och effektiva datatyper.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Rang och percentil inom grupper” gratis?

Ja – hela texten till ”Rang och percentil inom grupper” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Pandas & NumPy Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Pandas & NumPy Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Rang och percentil inom grupper”?

Beräkna rang inom grupper med groupby().rank() och skapa percentilgrupper med pd.qcut för relativa jämförelser. Ni övar på Pandas & NumPy Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Pandas & NumPy Academy?

Du behöver inga förkunskaper. Utbildningen i Pandas & NumPy Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Rang och percentil inom grupper”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Pandas & NumPy Academy-lektionen?

Ja. Varje Pandas & NumPy Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Rullande fönster
  2. Expanderande fönster
  3. Exponentiellt viktat glidande medelvärde
  4. Rang och percentil inom grupper
← Tillbaka till Pandas & NumPy Academy