Top-N per Group

Python · GroupBy & SQL-Style Analytics

Theory

'Top 2 orders in each city' is a classic window-function question. The most readable pandas answer is sort, then take the first n rows of each group: df.sort_values('amount', ascending=False).groupby('city').head(2). groupby().head(n) keeps the original columns and rows in sorted order; groupby().nth(0) picks a single position, and .tail(n) gives the bottom n.

Alternatives: df.groupby('city')['amount'].nlargest(2) returns just the column with a (city, original index) MultiIndex; and a rank filter, df[df.groupby('city')['amount'].rank(method='dense', ascending=False) <= 2], decides explicitly how ties behave - with 'dense' or 'min', tied values are all kept, so a city can return more than n rows. The single best row per group can also come from df.loc[df.groupby('city')['amount'].idxmax()]. In SQL this is QUALIFY ROW_NUMBER() OVER (PARTITION BY city ORDER BY amount DESC) <= 2.

Why we use it

Best sellers per category, top customers per region and latest events per user all need 'the first n rows of each group'. pandas does it in one chain instead of a loop over groups.

When to use it

Use sort + groupby().head(n) for exactly n rows per group, a rank filter when ties must be kept, and idxmax for the single best row. For top n overall, nlargest(n, col) is enough.

How it works

  1. Need top n rows per group
  2. Sort by the measure, highest first
  3. Group by the key (sorted order is kept inside groups)
  4. Keep ties beyond n? Yes: Filter rank(method='dense') <= n. No: Take groupby().head(n).
  5. n best rows for each group

Syntax

df.sort_values('col', ascending=False).groupby('key').head(n)
df[df.groupby('key')['col'].rank(method='dense', ascending=False) <= n]
df.loc[df.groupby('key')['col'].idxmax()]

Example

top2 = (df.sort_values('amount', ascending=False)
          .groupby('city').head(2)
          .sort_values(['city', 'amount'], ascending=[True, False]))

Key points

Python topics

Getting Started

Variables & Data Types

Operators

Strings

Lists

Tuples

Sets

Dictionaries

Control Flow

Loops

Functions & OOP

Working with Data

Tooling & Errors

File Handling

Exception Handling

NumPy Library

Pandas Basics

Data Cleaning

Combining DataFrames (SQL Joins & Unions)

GroupBy & SQL-Style Analytics

Reshaping & Workflow

Data Visualization

Machine Learning (Scikit-Learn)

Advanced Python & AI

T
Tech Town
Log InSign Up Free
Home SQL Python DSA Power BI Snowflake Databricks Spark Gen AI Practice Problems Contest Blog

Python for Data Analysts

From basics to business insights — the complete step-by-step Python roadmap. Click any topic in the sidebar to open it right here.

{{ sectionCount }}
Sections
{{ topicCount }}
Topics
Free
Forever
Hands-on practice Practice Python Online 141 Python questions for data analysts — strings, records, dates, statistics and regex — with hidden tests and instant verdicts. Start practising →
Section {{ sec.num }}

{{ sec.label }}

Python  /  {{ current.sectionLabel }}  /  {{ current.name }}

{{ current.name }}

Theory

{{ current.def }}

Why we use it

{{ rich.why }}

When to use it

{{ rich.when }}

Diagram

{{ rich.dg.caption }}

{{ tb.title }}
{{ c.v }}
{{ rich.dg.op }}
➜
{{ rich.dg.output.title }}
{{ c.v }}
{{ nd.label }}
{{ nd.sub }}
{{ nd.label }}
{{ nd.sub }}
{{ rich.dg.left.title }}
{{ it }}
{{ rich.dg.right.title }}
{{ it }}
Flowchart — how it works
{{ nd.text }}
{{ nd.text }}
◇ {{ nd.text }}
Yes → {{ nd.yes }}
No → {{ nd.no }}
Syntax
{{ current.syntax }}
Example
{{ current.example }}
▶ Try It Live — runs real Python 3.12 in your browser (first run loads the engine)
{{ liveOutput }}
{{ liveError }}
Key Points — click to check off as you learn
  • {{ pt.mark }} {{ pt.text }}

Share this topic