GroupBy transform (PARTITION BY)

Python · GroupBy & SQL-Style Analytics

Theory

agg() returns one row per group, but transform() returns one value per original row: each row gets the result computed over its own group. df.groupby('city')['amount'].transform('sum') gives every Jaipur row the Jaipur total and every Pune row the Pune total, in the same order and index as df, so you can assign it straight to a new column. This is exactly SQL's window aggregate SUM(amount) OVER (PARTITION BY city).

Any aggregation works: 'mean', 'max', 'min', 'count', 'size' or 'nunique', and several keys can be partitions: groupby(['city', 'month']). Typical uses are comparing each row with its group (amount - city_avg), share of group total (amount / city_total), flagging the group max (amount == transform('max')) and filling missing values with the group mean (s.fillna(s.groupby(key).transform('mean'))). transform also accepts a function, such as lambda s: (s - s.mean()) / s.std(), but built-in names are much faster.

Why we use it

Many calculations need both the detail row and a group-level number - each sale versus its city's average, each employee's share of department salary. transform keeps every row while adding the group value, with no merge needed.

When to use it

Use transform when the result must line up with the original rows. Use agg when you want one row per group. In SQL terms: GROUP BY collapses rows (agg), PARTITION BY keeps them (transform).

How it works

  1. df.groupby('city')['amount'].transform('mean')
  2. Split rows into city groups
  3. Compute the mean for each group
  4. Broadcast the group mean back to every row of that group
  5. Compare row with group? Yes: e.g. amount - city_avg, amount / city_total. No: Keep as a column.
  6. New column aligned with the original rows

Syntax

df['grp_total'] = df.groupby('key')['col'].transform('sum')
df.groupby(['k1', 'k2'])['col'].transform('mean')
s.fillna(s.groupby(df['key']).transform('mean'))

Example

df['city_avg'] = df.groupby('city')['amount'].transform('mean')
df['vs_avg'] = df['amount'] - df['city_avg']

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