Group Data with Groupby

Group data with groupby operations in Python for data science. This lesson covers core concepts, step-by-step methods, hands-on exercises, troubleshooting, and next steps for efficient data grouping.

Focus: group data with groupby operations

Sponsored

You have a DataFrame full of rows — sales, users, sensor readings — and you need answers like "What's the average revenue per region?" or "How many users signed up each day?" Doing this with loops and filters is slow, error-prone, and scales terribly when your data grows to millions of rows. The groupby operation in pandas is the missing key that unlocks split-apply-combine: split your data into groups, apply a function to each group, and combine the results. In this lesson, you'll master groupby operations — from basic grouping to advanced aggregations — so you can summarize and slice your data with confidence.

The problem this lesson solves

Raw tabular data rarely gives you the insight you need. Instead, you need summaries by category: daily sales totals, average rating per product, median income per city. Without groupby, you'd write fragile loop-based code that is verbose and slow:

# Painful manual grouping
import pandas as pd

df = pd.DataFrame({'region': ['North', 'South', 'North', 'East'],
                   'sales': [100, 200, 150, 300]})

regions = df['region'].unique()
result = {}
for r in regions:
    mask = df['region'] == r
    result[r] = df.loc[mask, 'sales'].sum()
print(result)
# {'North': 250, 'South': 200, 'East': 300}

The manual approach breaks down for multiple grouping columns, complex aggregations, and large datasets. It's also hard to read and maintain. Groupby operations solve this by providing a clean, declarative syntax that is both expressive and performant.

Core concept / mental model

Think of groupby as split-apply-combine — a three-step process:

  1. Split: Break the DataFrame into groups based on one or more columns.
  2. Apply: Run a function (e.g., sum, mean, count, custom) on each group independently.
  3. Combine: Stitch the results into a new DataFrame or Series.

Definitions

  • Grouping column(s): The column(s) that define the groups (e.g., region, product, date).
  • Aggregation: Applying a function that reduces each group to a single value (e.g., sum, mean, max).
  • Transformation: Applying a function that returns a value of the same shape as the group (e.g., z-score, fillna).
  • Filtration: Dropping groups based on a condition (e.g., keep groups with at least 3 rows).

Diagram-in-words

Imagine your data is a deck of cards, and you want the average value per suit. You split the deck into four piles by suit, compute the mean for each pile, then lay the four means side by side. groupby does exactly that — but with unlimited piles and sophisticated functions.

How it works step by step

Step 1: Import pandas and load your data

Always start with import pandas as pd. Load your data or create a sample DataFrame for practice.

Step 2: Call groupby() on the DataFrame

df.groupby('column') returns a GroupBy object — this is not the final result. It's a lazy intermediary that waits for you to specify an operation. You must follow it with an aggregation, transformation, or filter.

Step 3: Apply an aggregation

Chain a method like .sum(), .mean(), .count(), or .agg() to compute group-wise summaries. The default behavior is to apply the function to all numeric columns, but you can target specific columns.

Example sequence

# Step-by-step groupby
grouped = df.groupby('region')  # split
total = grouped['sales'].sum()   # apply + combine
print(total)

Pro tip: The GroupBy object is lazily evaluated. It doesn't compute anything until you trigger a reduction, so you can safely build complex pipelines without performance penalties.

Hands-on walkthrough

Let's work with a real-world-style dataset: sales records with region, product, and revenue.

Basic aggregation

import pandas as pd

df = pd.DataFrame({
    'region': ['North', 'South', 'North', 'East', 'South', 'East'],
    'product': ['Widget', 'Gadget', 'Widget', 'Gadget', 'Widget', 'Gadget'],
    'revenue': [100, 200, 150, 300, 250, 400],
    'units': [10, 20, 15, 30, 25, 40]
})

# Total revenue per region
region_total = df.groupby('region')['revenue'].sum()
print(region_total)
# region
# East     700
# North    250
# South    450
# Name: revenue, dtype: int64

# Average units per product
product_avg = df.groupby('product')['units'].mean()
print(product_avg)
# product
# Gadget    30.0
# Widget    16.667
# Name: units, dtype: int64

Multiple aggregations with agg

When you need different functions for different columns or a list of stats per column, use .agg():

# Multiple stats per group
summary = df.groupby('region').agg({
    'revenue': ['sum', 'mean', 'max'],
    'units': 'sum'
})
print(summary)

Group by multiple columns

You can group by several columns at once — the result has a MultiIndex:

multi = df.groupby(['region', 'product']).sum()
print(multi)
#                     revenue  units
# region product                   
# East   Gadget          700     70
# North  Widget          250     25
# South  Gadget          200     20
#        Widget          250     25

Using as_index=False for a clean result

By default, the grouping columns become the index. To keep them as regular columns, use as_index=False:

clean = df.groupby('region', as_index=False)['revenue'].sum()
print(clean)
#   region  revenue
# 0   East      700
# 1  North      250
# 2  South      450

Custom aggregation functions

You can pass any function that takes a Series and returns a scalar:

def range_value(s):
    return s.max() - s.min()

result = df.groupby('region')['revenue'].agg(range_value)
print(result)
# region
# East     100
# North     50
# South     50
# Name: revenue, dtype: int64

Pro tip: For performance, favor built-in methods (sum, mean, count, median) over custom Python functions when possible — pandas is heavily optimized for them.

Compare options / when to choose what

Task Use groupby + .agg() Use pivot_table Use crosstab
Group by one column df.groupby('col').sum() Similar but verbose Limited to two variables
Multiple aggregations .agg({'col': ['sum','mean']}) aggfunc can handle, but clunky Not designed for multiple
Two-way cross-tabulation Possible but unwieldy pivot_table ok Best fit
Need raw group-wise stats Best fit Produces same but less flexible Categorical counts only
Multi-level group handling Great Good Not applicable

When to choose what:

  • Use groupby when you need fine control over group-wise operations (custom functions, multiple aggregations).
  • Use pivot_table when you want a spreadsheet-like summary with rows and columns.
  • Use crosstab when you specifically need a frequency table of two categorical variables.

Troubleshooting & edge cases

Grouping by a column with missing values

By default, NaN values in the grouping column are excluded. To include them as a group, use dropna=False:

df = pd.DataFrame({'city': ['NY', None, 'LA'], 'sales': [100, 200, 150]})
result = df.groupby('city', dropna=False)['sales'].sum()
print(result)
# city
# LA     150
# NY     100
# NaN    200
# Name: sales, dtype: int64

Getting an empty or unexpected result

If your result is empty, check that the grouping column exists and has non-null values. Also, ensure the grouping column is of the right type (e.g., string vs. datetime).

Performance issues on large data

groupby is fast, but if you're using custom Python functions, consider vectorizing or using pandas.transform for parallel-friendly operations. Also, avoid grouping on high-cardinality columns (e.g., unique IDs) unless necessary.

KeyError on column name

If you get a KeyError, the column name might contain spaces or different casing. Double-check the DataFrame columns with df.columns.

Unexpected aggregation on non-numeric columns

When you call .sum() on a groupby without selecting a column, pandas tries to sum numeric columns only and may exclude others silently. Always select the columns you want to aggregate explicitly.

What you learned & what's next

You've learned the core of group data with groupby operations: the split-apply-combine mental model, how to create GroupBy objects, apply aggregations, use multiple columns, custom functions, and avoid common pitfalls. These skills are essential for data summarization and will appear in nearly every data science project.

Next lesson in this track will take you into merging and joining datasets — how to combine multiple DataFrames using merge and concat. That's a natural partner to groupby: you group what you have, and combine what you need. Keep practicing with real datasets to solidify your understanding.

Pro tip: Master groupby and you'll save yourself hours of manual data wrangling. It's one of the most powerful verbs in the pandas language.

Practice recap

Load a sample sales DataFrame and practice grouping by region and product. Try computing total revenue and average units per group, then use as_index=False to keep output clean. Bonus: add a custom function that returns the revenue range, and verify your output against a manual calculation.

Common mistakes

  • Forgetting that groupby returns a lazy GroupBy object — you must call an aggregation like .sum() to get a result.
  • Not using as_index=False, leading to surprising index-based results when you expect a plain column.
  • Calling .agg() on the whole DataFrame without selecting columns, causing errors when non-numeric columns exist.
  • Assuming NaN values in grouping columns are included by default — they are dropped unless you set dropna=False.
  • Using a custom Python function for aggregation when a built-in like sum or mean would be much faster.

Variations

  1. Use pivot_table for a spreadsheet-style summary with rows and columns instead of a long format.
  2. Use crosstab for frequency counts of two categorical variables.
  3. Use .transform() to add group-wise calculated values back to the original DataFrame, preserving row count.

Real-world use cases

  • Compute daily aggregated sales per store from a transaction log to monitor performance.
  • Calculate average test scores per classroom to identify teaching effectiveness trends.
  • Group sensor readings by device ID to find anomalous daily mean temperatures.

Key takeaways

  • groupby implements split-apply-combine — split data, apply a function, and combine results.
  • Always chain an aggregation, transformation, or filter after creating a GroupBy object.
  • Use .agg() to apply multiple aggregations to specific columns in one call.
  • Group by multiple columns for hierarchical grouping using a MultiIndex.
  • Missing values in grouping columns are dropped by default; use dropna=False to include them.
  • Built-in pandas methods are much faster than custom Python functions for group operations.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.