Pandas Data Cleaning & GroupBy

๐Ÿ Python 3.12+ ๐ŸŸข Chapter 56 of 65 ๐Ÿ“‚ Phase 11: Data Science and AI ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Missing Values (dropna, fillna) ยท Imputation Strategies ยท GroupBy Split-Apply-Combine ยท Aggregations (mean, sum, count) ยท Merging (Inner, Left, Outer) ยท Exporting Data
Master advanced data preparation and aggregation in Pandas: handling missing data with dropna() and fillna() imputation, the Split-Apply-Combine GroupBy paradigm, combining datasets with relational joins (pd.merge), and exporting cleaned datasets to CSV, Excel, and JSON.
1Handling Missing Data (NaN / None): Drop vs Imputation

Real-world datasets are messy, frequently containing missing fields due to sensor dropouts, optional user inputs, or data corruption.

The 2 Primary Strategies for Missing Data:

  1. Deletion (dropna()):
    • df.dropna(how='any'): Drops any row containing at least one NaN.
    • df.dropna(subset=['critical_column']): Drops rows only if a specific mandatory column is null.
  2. Imputation (fillna()): Replaces missing values with statistical measures to preserve sample size:
    • Mean / Median: For numerical distributions (median is robust against extreme outliers).
    • Mode (Most Frequent): For categorical columns.
    • Forward Fill (ffill): For time-series data (propagates the last known valid value forward).
๐Ÿ’ป Example 1: Missing Data Detection & Statistical Mean Imputation
# Missing Data Cleaning Simulation:
raw_sensor_data = [
    {"timestamp": "10:00", "temperature": 28.5, "humidity": 65},
    {"timestamp": "10:05", "temperature": None, "humidity": 68},  # Missing temp
    {"timestamp": "10:10", "temperature": 29.1, "humidity": None},# Missing humidity
    {"timestamp": "10:15", "temperature": 28.8, "humidity": 64}
]

# Calculate mean temperature of valid records for imputation:
valid_temps = [r["temperature"] for r in raw_sensor_data if r["temperature"] is not None]
mean_temp = sum(valid_temps) / len(valid_temps)

# Impute missing values:
cleaned_data = []
for record in raw_sensor_data:
    row = record.copy()
    if row["temperature"] is None:
        row["temperature"] = round(mean_temp, 1) # Mean Imputation!
    if row["humidity"] is None:
        row["humidity"] = 60 # Default fallback
    cleaned_data.append(row)

print(f"--- ๐Ÿงน Cleaned Sensor Data (Imputed Mean Temp: {mean_temp:.1f}ยฐC) ---")
for r in cleaned_data:
    print(r)
๐Ÿ” Pandas In-Memory Functions:

In real Pandas: df['temperature'] = df['temperature'].fillna(df['temperature'].mean()) performs this entire imputation in a single vectorized line.

2The GroupBy Paradigm: Split-Apply-Combine Strategy

The Split-Apply-Combine concept (formalized by Hadley Wickham) is the foundation of group analysis in data science:

  1. Split: Partition the dataset into groups based on keys (e.g. split sales by Region).
  2. Apply: Execute an aggregation function (such as mean(), sum(), count(), or std()) independently on each subgroup.
  3. Combine: Merge the resulting scalar metrics back into a unified summary DataFrame.
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ GROUPBY SPLIT-APPLY-COMBINE FLOW โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ Original Dataset: โ”‚ โ”‚ [Dept: Tech, Sal: 90k], [Dept: HR, Sal: 50k], [Dept: Tech, Sal: 80k] โ”‚ โ”‚ โ”‚ โ”‚ 1. SPLIT BY "Dept": โ”‚ โ”‚ โ”œโ”€โ”€ Tech Group -> [90k, 80k] โ”‚ โ”‚ โ””โ”€โ”€ HR Group -> [50k] โ”‚ โ”‚ โ”‚ โ”‚ 2. APPLY FUNCTION (mean()): โ”‚ โ”‚ โ”œโ”€โ”€ Tech -> (90k + 80k) / 2 = 85k โ”‚ โ”‚ โ””โ”€โ”€ HR -> 50k โ”‚ โ”‚ โ”‚ โ”‚ 3. COMBINE INTO SUMMARY TABLE: โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Department โ”‚ Average Salary โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Tech โ”‚ โ‚น85,000.00 โ”‚ โ”‚ โ”‚ โ”‚ HR โ”‚ โ‚น50,000.00 โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
๐Ÿ’ป Example 2: Split-Apply-Combine GroupBy Aggregation
# GroupBy Aggregation Simulation:
sales_transactions = [
    {"region": "South", "rep": "Balaji", "sales": 450000},
    {"region": "North", "rep": "Alex",   "sales": 320000},
    {"region": "South", "rep": "Chloe",  "sales": 580000},
    {"region": "North", "rep": "David",  "sales": 290000},
    {"region": "West",  "rep": "Elena",  "sales": 410000}
]

# Group sales by region and calculate totals:
regional_summary = {}
for item in sales_transactions:
    reg = item["region"]
    if reg not in regional_summary:
        regional_summary[reg] = {"total_sales": 0, "deal_count": 0}
    regional_summary[reg]["total_sales"] += item["sales"]
    regional_summary[reg]["deal_count"] += 1

print("--- ๐Ÿ“ˆ Regional Sales Aggregation Summary ---")
for reg, stats in regional_summary.items():
    avg = stats["total_sales"] / stats["deal_count"]
    print(f"โ€ข Region: {reg:6} | Total: โ‚น{stats['total_sales']:>10,} | Deals: {stats['deal_count']} | Avg Deal: โ‚น{avg:>8,}")
๐Ÿ” Pandas GroupBy Syntax:

In Pandas: df.groupby('region')['sales'].agg(['sum', 'mean', 'count']) produces this full statistical summary table in a single line!

โš ๏ธ Common Developer Pitfall: Performing Imputation on the Entire Dataset Before Splitting Training/Test Data

Calculating mean/median across the entire dataset before train_test_split causes Data Leakage (information from the test set leaks into the training pipeline). Always calculate statistics strictly on the training set and apply them to the test set.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Simulate merging two datasets: match customer orders with their corresponding customer addresses using customer_id as the join key.

Python 3 Practice Challenge โ–ถ Run in Compiler
customers = {1: "Balaji (Hyderabad)", 2: "Alex (Bengaluru)"}
orders = [{"order_id": 101, "cust_id": 1, "amount": 4500}, {"order_id": 102, "cust_id": 2, "amount": 1200}]

# Equivalent to pd.merge(orders_df, customers_df, on="cust_id", how="inner")
merged = []
for ord in orders:
    merged.append({
        "order_id": ord["order_id"],
        "customer": customers.get(ord["cust_id"], "Unknown"),
        "amount": ord["amount"]
    })

print("Merged Orders Table:")
for m in merged:
    print(f"Order #{m['order_id']}: {m['customer']} - โ‚น{m['amount']}")
Run This Challenge in Online Python IDE โ†’
โ“ Frequently Asked Questions (FAQ)

Q What is the difference between pd.merge() and pd.concat()?

pd.merge() combines DataFrames horizontally based on matching key columns (relational SQL JOIN). pd.concat() stacks DataFrames either vertically (appending rows) or horizontally (aligning indices).

Q What are the 4 join types supported by pd.merge()?

how="inner" (keeps only keys present in both DataFrames), how="left" (keeps all rows from left DataFrame), how="right" (keeps all from right), and how="outer" (keeps all rows from both, filling unmatched values with NaN).

Q How do I export a Pandas DataFrame to Excel (.xlsx)?

Use df.to_excel("filename.xlsx", index=False) using the openpyxl engine.

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on Python 3.12+ runtime ยท Last updated August 2026