Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
AI & Machine Learning Program
IITREICT-DSAI-2603
MODULE 2
Compiled Lecture Notes
NumPy • Pandas • Data Cleaning • EDA • Seaborn
Sessions Covered
• 5.1 NumPy Arrays & Performance
• 5.2 Vectorized Operations
• 5.3 Numeric Manipulation & Linear Algebra Basics
• 6.1 Introduction to Pandas DataFrames
• 6.2 Data Selection & Filtering
• 6.3 Summarizing & Grouping Data
• 7.1 Data Joins & Merges
• 7.2 Advanced Data Transformation
• 7.3 Text Manipulation in DataFrames
• 8.1 The Data Cleaning Workflow
• 8.2 Exploratory Data Analysis (EDA) Concepts
• 8.3 Visualizing Data with Seaborn
Interactive Module (IM) Resources
[Link]
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 5.1
NumPy Arrays & Performance
Foundation for scientific computing in Python
IM Resources: Click here to access interactive module resources
Learning Objectives
• Create and manipulate N-dimensional NumPy arrays
• Understand array broadcasting and vectorization
• Perform efficient array operations without loops
• Compare performance between NumPy and Python lists
• Apply NumPy for real-world data processing tasks
• Use indexing and slicing effectively
• Reshape and transform arrays
Part 1: NumPy Fundamentals
1.1 Introduction
NumPy (Numerical Python) is the fundamental package for scientific computing in Python.
Why NumPy?
• 50–100× faster than Python lists
• Foundation for pandas, scikit-learn, TensorFlow
• Efficient memory usage
• Comprehensive mathematical functions
Key Component: ndarray (N-dimensional array)
1.2 Creating Arrays
From Python Sequences:
import numpy as np
# 1D array
arr1d = [Link]([1, 2, 3, 4, 5])
# 2D array (matrix)
arr2d = [Link]([[1, 2, 3], [4, 5, 6]])
# 3D array
arr3d = [Link]([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
print([Link]) # (2, 2, 2)
Using Built-in Functions:
[Link]((3, 4)) # All zeros
[Link]((2, 3, 4)) # All ones
[Link](4) # 4x4 identity matrix
[Link](0, 10, 2) # [0 2 4 6 8]
[Link](0, 1, 5) # [0. 0.25 0.5 0.75 1.]
[Link](3, 3) # Uniform [0, 1)
[Link](3, 3) # Normal(0, 1)
[Link](0, 100, (3, 3))
1.3 Array Properties
arr = [Link]([[1, 2, 3], [4, 5, 6]])
[Link] # (2, 3)
[Link] # int64
[Link] # 2
[Link] # 6
[Link] # 8 (bytes per element)
[Link] # 48 (total bytes)
Type Range / Notes
int8 -128 to 127
int16 -32768 to 32767
int32/64 General integer
uint8 0 to 255 (unsigned)
float32/64 Floating point
bool True / False
Part 2: Array Operations
2.1 Vectorized Operations
Element-wise operations — no loops needed:
a = [Link]([1, 2, 3, 4])
b = [Link]([10, 20, 30, 40])
print(a + b) # [11 22 33 44]
print(a * b) # [10 40 90 160]
print(a ** 2) # [1 4 9 16]
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
print(a > 2) # [False False True True]
2.2 Broadcasting
Definition: NumPy automatically expands smaller arrays to match larger ones.
Rules: Arrays are compatible if (1) they have the same shape OR (2) one dimension is 1.
# Scalar broadcasting
arr = [Link]([1, 2, 3])
print(arr + 10) # [11 12 13]
# 1D + 2D broadcasting
arr2d = [Link]([[1, 2, 3], [4, 5, 6]])
arr1d = [Link]([10, 20, 30])
result = arr2d + arr1d
# [[11 22 33]
# [14 25 36]]
2.3 Aggregation Operations
arr = [Link]([[1, 2, 3], [4, 5, 6]])
[Link]() # 21 (all elements)
[Link](axis=0) # [5 7 9] (column sums)
[Link](axis=1) # [6 15] (row sums)
[Link]() # 3.5
[Link]() # standard deviation
[Link]() # index of min element
[Link]([1,2,3,4]) # [1 3 6 10]
Part 3: Indexing & Slicing
3.1 Basic Indexing
arr = [Link]([10, 20, 30, 40, 50])
arr[0] # 10
arr[-1] # 50
arr[1:4] # [20 30 40]
arr[::2] # [10 30 50]
arr[::-1] # [50 40 30 20 10]
# 2D indexing
arr2d = [Link]([[1,2,3],[4,5,6],[7,8,9]])
arr2d[0, 0] # 1
arr2d[:, 0] # [1 4 7] first column
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
arr2d[0:2, 1:3] # [[2 3],[5 6]]
3.2 Boolean Indexing
arr = [Link]([1, 2, 3, 4, 5, 6])
mask = arr > 3
print(arr[mask]) # [4 5 6]
print(arr[arr % 2 == 0]) # [2 4 6]
print(arr[(arr > 2) & (arr < 5)]) # [3 4]
Part 4: Array Manipulation
4.1 Reshaping
arr = [Link](12) # [0 1 2 ... 11]
[Link](3, 4) # 3 rows, 4 cols
[Link](3, -1) # auto columns
[Link]() # 1D copy
[Link]() # 1D view
4.2 Stacking and Splitting
a = [Link]([1, 2, 3])
b = [Link]([4, 5, 6])
[Link]([a, b]) # [[1 2 3],[4 5 6]]
[Link]([a, b]) # [1 2 3 4 5 6]
[Link](arr, 3) # split into 3 parts
Part 5: Performance & Best Practices
NumPy is 50–127× faster than Python lists due to:
• C implementation (compiled code)
• SIMD — Single Instruction Multiple Data (CPU parallelism)
• No Python interpreter overhead
• Contiguous memory layout for cache efficiency
# Typical performance comparison:
# Python list comprehension: 0.1523s
# NumPy vectorized: 0.0012s
# Speedup: 127x
✨ Best Practice: Always vectorize operations. Avoid Python loops over NumPy arrays. Use
built-in aggregations (sum, mean, etc.) for maximum performance.
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 5.2
Vectorized Operations
Master 'no-loop' math for high-speed data processing
IM Resources: Click here to access interactive module resources
Learning Objectives
• Master broadcasting rules and predict operation outcomes
• Write efficient element-wise operations for data transformations
• Use aggregations to extract meaningful statistics
• Apply boolean masking for complex data filtering
• Optimize code by eliminating loops
Part 1: The Power of Vectorization
Operation Loop (10M Vectorized (10M) Speedup
elements)
Squaring 2.1s 0.012s 175×
Addition 1.8s 0.009s 200×
Sqrt 2.5s 0.015s 167×
Complex math 4.2s 0.025s 168×
# Celsius to Fahrenheit — vectorized
celsius = [Link](-30, 45, 10_000_000)
fahrenheit = celsius * 9/5 + 32 # 0.018s vs 3.245s with loop
Part 2: Broadcasting Deep Dive
The Three Broadcasting Rules
• Rule 1 — Rank Matching: Prepend 1s to the shape of the smaller array
• Rule 2 — Dimension Compatibility: Each dimension must be equal OR one of them is 1
• Rule 3 — Output Shape: Result shape is the maximum size along each dimension
# Compatible shapes
(3, 4) and (4,) → result (3, 4) ✓
(3, 1) and (3, 4) → result (3, 4) ✓
# Incompatible shapes
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
(3, 4) and (3,) → Incompatible! ✗
(3, 4) and (2, 4) → Incompatible! ✗
Practical: Data Normalization
# Z-score Normalization
scores = [Link](50, 100, (100, 5))
mean = [Link](axis=0) # shape (5,)
std = [Link](axis=0) # shape (5,)
normalized = (scores - mean) / std # Broadcasting!
# Min-Max Scaling
mn = [Link](axis=0)
mx = [Link](axis=0)
scaled = (scores - mn) / (mx - mn)
Part 3: Element-wise Operations
prices = [Link]([10.50, 25.00, 15.75, 30.25])
quantities = [Link]([2, 1, 3, 2])
item_totals = prices * quantities
discounted = prices * 0.9
# Compound interest: P * (1 + r)^n
principal = [Link]([1000, 5000, 10000, 25000])
future_value = principal * (1 + 0.07) ** 10
Part 4: Aggregations
scores = [Link]([78, 85, 92, 67, 88, 91, 74, 82, 95, 70])
[Link]() # 82.2
[Link](scores) # 83.5
[Link]() # 9.29
[Link](scores, 25) # Q25
[Link](scores, 75) # Q75
# Multi-dimensional aggregation
sales = [Link]([[100,150,120],[110,160,130],[120,170,140],[130,180,150]])
[Link](axis=1) # quarterly totals: [370, 400, 430, 460]
[Link](axis=0) # product totals: [460, 660, 540]
[Link](axis=1).argmax() # best quarter index
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Part 5: Boolean Masking (Advanced)
Multi-condition Filtering
# Employee data: [age, experience, salary]
employees = [Link]([[25,2,45000],[35,10,85000],[42,15,95000],
[28,5,60000],[50,20,110000],[32,8,75000]])
# Senior employees (age > 40 OR experience > 15)
senior = (employees[:,0] > 40) | (employees[:,1] > 15)
senior_employees = employees[senior]
[Link]() for Conditional Assignment
temperatures = [Link]([28, 45, 72, 95, 68, 55, 82])
classification = [Link](temperatures > 80, 'Hot',
[Link](temperatures >= 60, 'Mild', 'Cold'))
✅ Performance Best Practices: Vectorize everything • Use broadcasting instead of
expanding arrays • Chain operations: data[data > 0].mean() • Use built-in aggregations •
Never use Python loops or .append() on NumPy arrays
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 5.3
Numeric Manipulation & Linear Algebra Basics
Reshaping, transposition, matrix multiplication & synthetic data
IM Resources: Click here to access interactive module resources
Learning Objectives
• Reshape and transpose NumPy arrays to match ML model input requirements
• Perform matrix multiplication using [Link]() and the @ operator
• Generate synthetic datasets using NumPy's random module
• Apply these operations to realistic ML data transformation tasks
Core Concept 1: Array Reshaping
The reshape() Method
Rule: The product of new shape dimensions must equal the product of old shape dimensions.
arr = [Link](12) # [0 1 2 ... 11]
[Link](3, 4) # 3 rows, 4 cols
[Link](2, 2, 3) # 3D array
# The -1 wildcard
[Link](-1, 6) # auto rows, 6 cols -> (4, 6)
[Link](4, -1) # 4 rows, auto cols -> (4, 6)
[Link](-1) # flatten to 1D
flatten() vs ravel()
Method Returns When to Use
flatten() Copy — changes don’t affect original Safety, debugging
ravel() View — changes may affect original Speed, memory efficiency
ML Application: Preparing Image Data
# 100 grayscale images, 28x28 pixels
images = [Link](0, 256, size=(100, 28, 28))
print([Link]) # (100, 28, 28)
# Flatten each image for a fully connected layer
images_flat = [Link](100, -1)
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
print(images_flat.shape) # (100, 784) <- MNIST preprocessing
Core Concept 2: Transposition
Using .T and [Link]()
Transposition flips a matrix along its diagonal — rows become columns and columns become rows.
A = [Link]([[1, 2, 3],
[4, 5, 6]]) # shape (2, 3)
AT = A.T # shape (3, 2)
# [[1, 4]
# [2, 5]
# [3, 6]]
# 3D: custom axis ordering
arr = [Link]((2, 3, 4))
[Link](arr, (0, 2, 1)).shape # (2, 4, 3)
Core Concept 3: Matrix Multiplication
The Rule: Inner Dimensions Must Match
A (m × k) @ B (k × n) = C (m × n)Each output element C[i,j] is the dot product of row i of A
and column j of B.
A = [Link]([[1, 2], [3, 4]]) # (2, 2)
B = [Link]([[5, 6], [7, 8]]) # (2, 2)
# Three equivalent methods:
C = [Link](A, B) # method 1
C = A @ B # method 2 (preferred)
C = [Link](A, B) # method 3
# CRITICAL DISTINCTION:
A * B # element-wise: [[5,12],[21,32]]
A @ B # matrix mult: [[19,22],[43,50]]
ML Application: Simulating a Linear Layer
X = [Link](8, 4) # 8 samples, 4 features
W = [Link](4, 3) # 4 inputs -> 3 outputs
b = [Link](3) # bias per output neuron
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
output = X @ W + b # (8, 3) <- this is [Link] internally!
Core Concept 4: Generating Synthetic Data
Setting the Random Seed
[Link](42) # Traditional
rng = [Link].default_rng(42) # Modern (preferred)
Common Distributions
rng = [Link].default_rng(42)
[Link]((3, 4)) # Uniform [0, 1)
rng.standard_normal((3, 4)) # Normal(0, 1)
[Link](loc=5.0, scale=2.0, size=(3, 4)) # Custom normal
[Link](low=0, high=100, size=(3, 4)) # Integer range
Synthetic Classification Dataset
[Link](0)
n_samples = 200
# Class 0: centered at (2, 2)
class_0 = [Link](n_samples//2, 2) + [Link]([2, 2])
# Class 1: centered at (-2, -2)
class_1 = [Link](n_samples//2, 2) + [Link]([-2, -2])
X = [Link]([class_0, class_1]) # (200, 2)
y = [Link]([[Link](100), [Link](100)]) # (200,)
Operation Where It's Used
reshape() Flattening images for dense layers; batch processing
.T / transpose() Covariance computation; attention score alignment
@ / matmul() Linear layers; PCA; attention mechanisms
[Link]() Weight initialization; synthetic benchmarks
[Link]() Identity operations; regularization terms
💡 Key Insight: Shape awareness is a professional skill. Before every operation, know your
input shapes and expected output shapes. When in doubt, print .shape
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 6.1
Introduction to Pandas DataFrames
From raw data to structured tables
IM Resources: Click here to access interactive module resources
Learning Objectives
• Distinguish between a Pandas Series and a DataFrame and construct both from scratch
• Read tabular data from CSV and Excel files using pd.read_csv() and pd.read_excel()
• Apply core inspection methods: .head(), .tail(), .shape, .dtypes, .info(), .describe()
• Perform basic DataFrame operations: column selection, row filtering, summary statistics
Situation Use
Pure numerical computation, matrix math NumPy
Tabular data with mixed types Pandas
ML model input (after preprocessing) NumPy arrays
Reading CSV/Excel files Pandas
Grouping, filtering, aggregating Pandas
Core Concept 1: The Pandas Series
A Series is a one-dimensional labeled array with values, index, name, and dtype.
import pandas as pd
# From a list with custom index
scores = [Link]([88, 72, 95, 60, 83],
index=['Priya','Arjun','Sneha','Dev','Meera'],
name='exam_score')
print(scores['Sneha']) # 95
print([Link]()) # 79.6
# From a dictionary
city_pop = [Link]({'Mumbai': 20.7, 'Delhi': 19.8, 'Bangalore': 12.3})
# Key attributes
[Link] # underlying NumPy array
[Link] # RangeIndex or custom index
[Link] # data type
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
[Link] # (5,)
[Link] # series name
Core Concept 2: The DataFrame
A DataFrame is a two-dimensional labeled data structure — a table where each column is a Series
sharing the same index.
# Method 1: From dictionary of lists
data = {'name': ['Priya','Arjun','Sneha'],
'age': [28, 34, 25],
'salary': [75000.0, 92000.0, 61000.0]}
df = [Link](data)
# Method 2: From list of dicts (JSON/API)
records = [{'name':'Priya','age':28}, {'name':'Arjun','age':34}]
df = [Link](records)
# Method 3: From NumPy array
arr = [Link](4, 3)
df = [Link](arr, columns=['f1','f2','f3'])
Core Concept 3: Reading Files
CSV Files
df = pd.read_csv('sales_data.csv')
# With parameters
df = pd.read_csv('[Link]',
sep=',', # delimiter
nrows=100, # first 100 rows only
na_values=['N/A','na','missing'], # treat as NaN
parse_dates=['date_column'], # auto-parse dates
usecols=['id','revenue','date'] # specific columns only
)
Excel Files
df = pd.read_excel('[Link]') # first sheet
df = pd.read_excel('[Link]', sheet_name='Q3') # named sheet
all_sheets = pd.read_excel('[Link]', sheet_name=None) # all sheets
# Writing
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
df.to_csv('[Link]', index=False)
df.to_excel('[Link]', sheet_name='Results', index=False)
Core Concept 4: The First-Contact Protocol
Run these commands every time you load a new dataset:
[Link] # (200, 6) -> 200 rows, 6 columns
[Link]() # column names
[Link] # data type per column
[Link]() # first 5 rows
[Link](3) # last 3 rows
[Link]() # structure + non-null counts + dtypes
[Link]() # statistical summary (numeric cols)
[Link]().sum() # missing value count per column
df['col'].value_counts() # frequency distribution
💡 Reading .describe() output: count < total rows means missing values. Large gap between
mean and 50th percentile (median) signals skewed distribution. Check min/max for obvious
outliers immediately.
Column Selection and Filtering
# Single column -> Series
salary_series = df['salary']
# Multiple columns -> DataFrame
subset = df[['name', 'salary', 'department']]
# Boolean filtering
high_earners = df[df['salary'] > 80000]
engineers = df[df['department'] == 'Engineering']
senior_eng = df[(df['department']=='Engineering') & (df['experience_years']>=10)]
selected = df[df['department'].isin(['Engineering','Marketing'])]
# Adding columns
df['annual_bonus'] = df['salary'] * 0.10
df['seniority'] = [Link](df['experience_years'] >= 10, 'Senior', 'Junior')
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 6.2
Data Selection & Filtering
Precise row and column extraction in Pandas
IM Resources: Click here to access interactive module resources
Learning Objectives
• Apply boolean indexing to filter DataFrame rows based on conditions
• Use .loc for label-based access and .iloc for position-based access
• Combine multiple filter conditions using &, |, and ~ operators
• Select specific columns using multiple syntactic patterns
Core Concept 1: Boolean Indexing
Step 1: Evaluate a condition on a column → produces a boolean Series. Step 2: Use that boolean
Series as an index → DataFrame returns only True rows.
# One-liner (most common)
high_earners = df[df['salary'] > 80000]
# Common operators
df[df['age'] == 30] # equal
df[df['salary'] >= 70000] # gte
df[df['is_active'] == True] # boolean col
df[df['salary'].isna()] # null values
df[df['salary'].notna()] # non-null values
# .isin() for multiple values
df[df['department'].isin(['Engineering','Finance'])]
df[~df['department'].isin(['HR','Marketing'])] # exclusion
# String filtering
df[df['city'].[Link]('bad', case=False)]
df[df['department'].[Link]('En')]
Core Concept 2: .loc vs .iloc
Access Stands for Uses Slice Behavior
or
.loc Label-based Row labels + column names Inclusive on both ends
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
.iloc Integer-location Row & column position Exclusive on right end (standard
(0-indexed) Python)
.loc Examples
[Link][5] # row with label 5
[Link][5, 'salary'] # single cell
[Link][0:4] # rows 0,1,2,3,4 (INCLUSIVE!)
[Link][0:4, ['name','department','salary']]
# Most common: boolean filter + column selection
[Link][df['city'] == 'Mumbai', ['name','salary','department']]
.iloc Examples
[Link][0] # first row
[Link][-1] # last row
[Link][0:5] # rows 0,1,2,3,4 (EXCLUSIVE end!)
[Link][0, 6] # first row, 7th column
[Link][0:5, 0:3] # first 5 rows, first 3 cols
[Link][:, 3] # all rows, 4th column only
[Link][-3:, -2:] # last 3 rows, last 2 cols
⚠️ Critical Difference: [Link][0:4] returns 5 rows (0,1,2,3,4 - inclusive). [Link][0:4] returns 4
rows (0,1,2,3 - exclusive). This is the most common off-by-one bug when switching between
.loc and .iloc.
Core Concept 3: Multiple Conditions
Operator Meaning Do NOT Use
& AND — both conditions True and
| OR — at least one True or
~ NOT — invert the condition not
# AND: employees from Mumbai earning > 80,000
result = df[(df['city'] == 'Mumbai') & (df['salary'] > 80000)]
# OR: employees from Delhi or Chennai
metro = df[(df['city'] == 'Delhi') | (df['city'] == 'Chennai')]
# Cleaner with .isin():
metro = df[df['city'].isin(['Delhi','Chennai'])]
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# NOT: exclude HR department
non_hr = df[~(df['department'] == 'HR')]
# CRITICAL: parentheses are REQUIRED!
# WRONG: df[df['city']=='Mumbai' | df['city']=='Delhi' & df['salary']>80000]
# RIGHT: df[((df['city']=='Mumbai') | (df['city']=='Delhi')) & (df['salary']>80000)]
.query() — SQL-Like Alternative
[Link]("city in ['Mumbai','Delhi'] and salary > 80000")
# With Python variables (prefix with @)
min_salary = 80000
[Link]('salary > @min_salary and performance == 5')
# Range query
[Link]('20 <= age <= 35')
Core Concept 4: Column Selection
# Single column -> Series
df['salary']
# Multiple columns -> DataFrame
df[['name','department','salary']]
# By data type
df.select_dtypes(include=['number'])
df.select_dtypes(include=['object']) # strings
df.select_dtypes(exclude=['bool'])
# Combined: filter rows AND select columns in one .loc call
result = [Link][
(df['city'] == 'Mumbai') & (df['salary'] > 70000),
['name','department','salary','performance']
]
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 6.3
Summarizing & Grouping Data
From raw rows to business insights
IM Resources: Click here to access interactive module resources
Learning Objectives
• Apply groupby() with single and multiple columns to slice data into groups
• Use aggregation functions — sum, mean, count, min, max, agg — to compute group-level
summaries
• Build pivot tables with pd.pivot_table() to create cross-tabulated views
• Read descriptive statistics from .describe() and understand each metric
• Explain what a MultiIndex is and how to flatten it with reset_index()
Part 1: groupby() Basics
Pattern: `[Link]("column")["target"].aggregation()`
# Total sales by city
[Link]('city')['sales'].sum()
# Multiple columns -> MultiIndex
[Link](['city','product'])['sales'].sum()
# Always select the target column explicitly
[Link]('city')['sales'].sum() # CORRECT
[Link]('city').sum() # works but sums ALL numeric cols
Part 2: Aggregation Functions
# Single aggregation
[Link]('department')['salary'].mean()
[Link]('department')['salary'].max()
[Link]('department')['salary'].count()
# Multiple aggregations with .agg()
summary = [Link]('department')['salary'].agg(['mean','max','count'])
# Named aggregations (cleaner output)
summary = [Link]('department')['salary'].agg(
avg_salary='mean',
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
top_salary='max',
headcount='count'
)
Part 3: Pivot Tables
pivot = pd.pivot_table(
df,
values = 'revenue', # column to aggregate
index = 'month', # row labels
columns = 'category', # column headers
aggfunc = 'sum', # aggregation function
fill_value = 0 # replace NaN with 0 (IMPORTANT!)
)
⚠️ Always set fill_value=0 for numeric data in pivot tables. Without it, missing combinations
become NaN, which breaks downstream calculations.
Part 4: Descriptive Statistics with .describe()
df['salary'].describe()
# count 200.0 <- non-null count
# mean 69832.4
# std 14987.3 <- spread
# min 25341.2 <- check for outliers
# 25% 59823.1 <- Q1
# 50% 70156.7 <- median
# 75% 80012.4 <- Q3
# max 114532.0 <- check for outliers
# After groupby
[Link]('department')['salary'].describe()
Statistic What to Look For
count If less than total rows → missing values present
mean vs 50% Large gap → data is skewed by outliers
min / max Spot obvious errors or extreme outliers immediately
std High std = lots of variation; low std = tightly clustered
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Part 5: MultiIndex Basics
result = [Link](['city','product'])['sales'].sum()
# MultiIndex([('Bangalore','Laptop'), ('Bangalore','Phone'), ...])
# Accessing
result['Bangalore'] # all products in Bangalore
result['Bangalore']['Laptop'] # specific combination
# Flatten to regular DataFrame
result_df = result.reset_index()
# Now: city | product | sales (clean, flat DataFrame)
💡 Workflow: raw rows → groupby() → aggregation → readable summary → insight. The
whole pipeline answers: 'What’s the pattern?' rather than just 'What happened?'
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 7.1
Data Joins & Merges
Combining DataFrames by matching keys
IM Resources: Click here to access interactive module resources
Learning Objectives
• Identify the four core join types and explain what each returns
• Apply [Link]() using shared keys, different key names, and suffixes
• Distinguish between a join and a concatenation
• Execute special joins — cross joins, column-to-index, index-to-index
• Debug merged outputs by recognising where NaN values appear
The Four Core Join Types
T1 = [Link]({'ID':[1,2,3,4], 'Name':['Aarav','Priya','Ravi','Sneha']})
T2 = [Link]({'ID':[2,3,4,5], 'Score':[88,75,91,60]})
# IDs 2,3,4 appear in both. ID 1 only in T1. ID 5 only in T2.
Join Type Returns Use When
INNER Only matching rows from BOTH Only care about records in both
tables
LEFT All rows from left, matching from Left table is master list, keep all
right (NaN if no match)
RIGHT All rows from right, matching from Mirror of left; prefer rewriting as LEFT
left (NaN if no match)
OUTER All rows from BOTH tables (NaN Auditing, gap analysis
where no match)
# Inner join - only IDs 2, 3, 4
[Link](T1, T2, on='ID', how='inner')
# Left join - IDs 1,2,3,4; Score NaN for ID 1
[Link](T1, T2, on='ID', how='left')
# Right join - IDs 2,3,4,5; Name NaN for ID 5
[Link](T1, T2, on='ID', how='right')
# Outer join - IDs 1,2,3,4,5 with NaN where missing
[Link](T1, T2, on='ID', how='outer')
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Join Parameters
Different Column Names — left_on / right_on
result = [Link](customers, orders,
left_on='customer_id',
right_on='cust_id',
how='left')
Resolving Name Conflicts — suffixes
result = [Link](orders, payments, on='order_id',
suffixes=('_order', '_payment'))
# Without suffixes: Pandas defaults to _x, _y (unreadable)
# Columns: order_id, amount_order, status_order, amount_payment, status_payment
Index-Based Joins
# Column-to-index join
[Link](df_left, df_right, left_on='ID', right_index=True, how='inner')
# Index-to-index join
[Link](df_left, df_right, left_index=True, right_index=True, how='inner')
Special Join: Cross Join
colours = [Link]({'colour': ['Red','Blue']})
sizes = [Link]({'size': ['S','M','L','XL']})
cross = [Link](colours, sizes, how='cross')
# 2 x 4 = 8 rows: every colour paired with every size
# Use for: product variants, scheduling grids, test datasets
⚠️ Warning: Cross joins on large tables explode in size. A 1,000-row table crossed with
another 1,000-row table = 1,000,000 rows. Always verify table sizes first.
Concatenation vs Join
Feature [Link]() [Link]()
Purpose Combine by matching rows on a key Stack tables vertically/horizontally
Requires a key? Yes (usually) No
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Direction Horizontal (adds columns) Vertical (axis=0) or Horizontal (axis=1)
Use case Joining customer & orders tables Stacking Jan+Feb+Mar data
# [Link] - stack rows from multiple DataFrames
all_orders = [Link]([jan, feb, mar], axis=0, ignore_index=True)
# ALWAYS use ignore_index=True to prevent duplicate index values
Multi-Table Joins
# Chain multiple [Link]() calls
step1 = [Link](customers, orders, on='customer_id', how='left')
final = [Link](step1, payments, on='order_id', how='left')
# Result: customers who haven't ordered get NaN in order cols
# orders without payment get NaN in payment cols
🧠 Mental model: A join is like a zipper — connects two strips by matching teeth (keys).
Concatenation is like taping strips end-to-end — no matching, just extension.
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 7.2
Advanced Data Transformation
.apply(), .map(), pivot/melt, and datetime handling
IM Resources: Click here to access interactive module resources
Learning Objectives
• Apply custom and built-in functions using .apply(), .map(), and .replace()
• Reshape DataFrames between wide and tall formats using .pivot_table() and .melt()
• Parse and engineer date/time features using pd.to_datetime() and the .dt accessor
• Choose the right transformation tool for a given data problem
Core Concept 1: .apply(), .map(), .replace()
Why These Exist
Python for loops on DataFrames are slow. Pandas' vectorised operations process entire arrays using
compiled C/NumPy code — 5–50× faster.
.apply() — The Custom Transformer
# On a single column (Series)
df['salary_thousands'] = df['salary'].apply(lambda x: round(x/1000, 1))
# Named function for complex logic
def classify_salary(salary):
if [Link](salary): return 'Unknown'
elif salary >= 90000: return 'Senior'
elif salary >= 65000: return 'Mid'
else: return 'Junior'
df['salary_band'] = df['salary'].apply(classify_salary)
# On multiple columns (axis=1)
def performance_flag(row):
avg = (row['score_q1'] + row['score_q4']) / 2
trend = row['score_q4'] - row['score_q1']
if avg >= 80 and trend > 5: return 'Improving High'
elif avg >= 80: return 'Stable High'
else: return 'Standard'
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
df['perf_flag'] = [Link](performance_flag, axis=1)
.map() — Simple One-to-One Substitution
# Dictionary mapping
code_to_name = {'ENG':'Engineering','SLS':'Sales','HR':'Human
Resources','MKT':'Marketing'}
df['dept_full'] = df['dept_code'].map(code_to_name)
# Numeric encoding
status_encode = {'Active':1,'Inactive':0,'On Leave':2}
df['status_code'] = df['status'].map(status_encode)
# Note: values NOT in dictionary become NaN
.replace() — Find and Replace
# Unmatched values STAY unchanged (unlike .map() which makes them NaN)
df['region'] = df['region'].replace({'North':'N','South':'S','East':'E','West':'W'})
# Replace multiple values with one
df['dept_code'] = df['dept_code'].replace(['ENG','MKT'], 'Technical')
# Regex replacement
df['name'] = df['name'].replace(r'Employee_(\d+)', r'EMP-\1', regex=True)
Situation Use
Map all values; NaN for missing is OK .map(dict)
Replace specific values; keep everything else .replace(dict)
Complex conditional logic on a column .apply(function)
Complex logic using multiple columns per row .apply(function, axis=1)
Core Concept 2: Pivot and Melt
Format Shape Best For
Wide One row per subject; time/category in Human-readable reports
columns
Tall One row per observation Machine-friendly: groupby, filter, plot
.melt() — Wide to Tall
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
scores_tall = scores_wide.melt(
id_vars = 'emp_id', # keep as-is
value_vars = ['score_q1','score_q2','score_q3','score_q4'], # unpivot
var_name = 'quarter', # new label column
value_name = 'score' # new value column
)
# Clean up labels: 'score_q1' -> 'Q1'
scores_tall['quarter'] =
scores_tall['quarter'].[Link]('score_q','Q').[Link]()
.pivot_table() — Tall to Wide (with Aggregation)
pivot = df.pivot_table(
values = 'salary', # what to aggregate
index = 'department', # row labels
columns = 'region', # column labels
aggfunc = 'mean', # aggregation function
fill_value = 0 # replace NaN with 0
)
# Multiple aggregations
pivot = df.pivot_table(
values='salary', index='department',
aggfunc={'salary': ['mean','count','max']}
)
Core Concept 3: Date/Time Handling
pd.to_datetime() — The Converter
# After loading, dates are 'object' (string) dtype
df['join_date'] = pd.to_datetime(df['join_date'])
# Specify format explicitly
df['join_date'] = pd.to_datetime(df['join_date'], format='%Y-%m-%d')
# Handle bad values safely
df['join_date'] = pd.to_datetime(df['join_date'], errors='coerce')
# 'coerce' -> unparseable values become NaT (Not a Time)
The .dt Accessor
df['join_year'] = df['join_date'].[Link]
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
df['join_month'] = df['join_date'].[Link]
df['join_quarter'] = df['join_date'].[Link]
df['day_of_week'] = df['join_date'].[Link] # 0=Mon, 6=Sun
df['day_name'] = df['join_date'].dt.day_name() # 'Monday', etc.
df['is_weekend'] = df['join_date'].[Link] >= 5
Date Arithmetic
# Tenure in days
today = [Link]()
df['tenure_days'] = (today - df['join_date']).[Link]
df['tenure_years'] = df['tenure_days'] / 365.25
# Filter by date range
recent = df[df['join_date'].between('2020-01-01','2022-12-31')]
df_2021 = df[df['join_date'].[Link] == 2021]
df_q1 = df[df['join_date'].[Link] == 1]
💡 Think of it this way: .apply() is your Swiss Army knife • .map() is your dictionary translator
• .melt() is your flattener • .pivot_table() is your summariser • .dt is your calendar
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 7.3
Text Manipulation in DataFrames
Cleaning, extracting and standardizing text columns
IM Resources: Click here to access interactive module resources
Learning Objectives
• Apply Pandas string operations through the .str accessor to clean entire text columns at once
• Use regular expressions with .[Link](), .[Link](), and .[Link]()
• Standardise categorical columns by fixing casing, whitespace, typos, and inconsistent labels
• Build a complete text-cleaning pipeline from raw data to analysis-ready shape
Core Concept 1: The .str Accessor
Without `.str`, calling string methods on a Pandas Series raises an AttributeError. The `.str` accessor
applies element-wise string operations across the whole column.
df['name'].lower() # ❌ AttributeError
df['name'].[Link]() # ✅ applies to every element
Case and Whitespace Methods
df['name'].[Link]() # all lowercase
df['name'].[Link]() # ALL UPPERCASE
df['name'].[Link]() # Title Case Every Word
df['name'].[Link]() # remove leading/trailing whitespace
df['name'].[Link]() # left only
df['name'].[Link]() # right only
# Chaining operations
df['name_clean'] = df['name'].[Link]().[Link]()
Replace, Split, Contains
# Remove punctuation
df['city_clean'] =
df['city'].[Link]().[Link]().[Link]('.','',regex=False)
# Split email into parts
email_parts = df['email'].[Link]().[Link]('@', expand=True)
email_parts.columns = ['username','domain']
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# Boolean filters
gmail_users = df[df['email'].[Link]().[Link]('@[Link]')]
df['city'].[Link]().[Link]('mumbai', na=False) # na=False is critical!
⚠️ Always add na=False to .[Link](). If the column has NaN values, the result is NaN
(not False) without this parameter, which can break downstream boolean filters.
Core Concept 2: Regex in Pandas
Core Regex Patterns
Pattern Meaning Example
\\d Any single digit 9
\\d+ One or more digits 9876543210
\\w Word character A, b, 1, _
(letter/digit/underscore)
\\s Whitespace character space, tab
. Any character (except newline) a, 9, @
^ Start of string
$ End of string
() Capturing group — what
.[Link]() returns
Extracting Phone Numbers
# Pattern: exactly 10 consecutive digits
df['phone_clean'] = df['phone'].[Link](r'(\d{10})')
# Input: 'Call me at 9876543210 anytime'
# Output: '9876543210'
Extracting Salary Numbers
df['salary_raw'] = df['salary_text'].[Link](r'(\d[\d,]*)')
df['salary'] = df['salary_raw'].[Link](',','',regex=False).astype(float)
Cleaning with Regex Replace
# Remove all non-alphanumeric characters
df['name_alpha'] = df['name'].[Link](r'[^a-zA-Z\s]','',regex=True).[Link]()
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# Remove consecutive whitespace
df['name_alpha'] = df['name_alpha'].[Link](r'\s+',' ',regex=True)
# Remove trailing punctuation
df['city_clean'] =
df['city'].[Link]().[Link]().[Link](r'[.,!?]+$','',regex=True)
Core Concept 3: Cleaning Categorical Data
Strategy 1: Normalise Case and Whitespace
# 'Premium', 'PREMIUM', 'premium ' -> all 3 become 'Premium'
df['category_clean'] = df['category'].[Link]().[Link]()
Strategy 2: .replace() for Explicit Mapping
feedback_map = {
'Excellent service!': 'Excellent',
'GOOD product': 'Good',
'very bad quality...':'Bad',
'OK': 'Neutral',
}
df['feedback_clean'] = df['feedback'].replace(feedback_map)
Strategy 3: Fuzzy Matching with .[Link]()
import numpy as np
conditions = [
df['feedback'].[Link]().[Link]('excel', na=False),
df['feedback'].[Link]().[Link]('good|great|nice', na=False),
df['feedback'].[Link]().[Link]('bad|poor|terrible', na=False),
]
df['sentiment'] = [Link](conditions, ['Excellent','Good','Bad'],
default='Neutral')
Strategy Use When
.[Link]().[Link]() Only case/whitespace inconsistencies
.replace(dict) Explicit many-to-one mapping; keep unmatched values
.map(dict) Complete substitution; NaN flags unmapped values
.[Link]() + [Link]() Pattern-based fuzzy classification
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
💡 Build Pipelines: df['name'].[Link]().[Link]().[Link](...) — chain operations for
readable, reproducible, debuggable code.
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 8.1
The Data Cleaning Workflow
Handling nulls, duplicates, and outliers
IM Resources: Click here to access interactive module resources
Learning Objectives
• Identify and handle missing values using drop, fillna with mean/median/mode, or 'unknown'
• Remove duplicate rows using [Link]() and df.drop_duplicates()
• Detect and handle outliers using the IQR-based statistical method
• Automate cleaning with loops that inspect column data types
• Understand why data quality matters: Garbage In, Garbage Out
Data cleaning will take 60% of your time in real corporate data science projects. It is the
foundation of every reliable model.
Step 1: Detecting Missing Values
# Always run these first
[Link]().sum() # count missing per column
[Link]().mean() * 100 # percentage missing per column
Step 2: Filling Missing Values
Numerical Columns
Situation Strategy Code
Symmetric distribution, Fill with MEAN df['age'].fillna(df['age'].mean(), inplace=True)
no extremes
Extreme outliers present, Fill with MEDIAN df['amount'].fillna(df['amount'].median(),
skewed inplace=True)
60%+ missing Consider dropping [Link](columns=['col'])
column
Categorical Columns
# Option 1: Mode (most frequent) - use with caution
df['city'].fillna(df['city'].mode()[0], inplace=True)
# mode() returns a Series; index [0] gets the top value
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# Option 2: 'Unknown' - honest when no clear answer
df['name'].fillna('unknown', inplace=True)
⚠️ Use mode only if the missing value genuinely belongs to the most frequent category.
Blindly filling with mode shifts the distribution. When in doubt, use 'unknown'.
Step 3: Removing Duplicates
[Link]() # True for duplicate rows
df.drop_duplicates(inplace=True, ignore_index=True)
# Duplicates on a subset of columns
df.drop_duplicates(subset=['customer','item'], inplace=True)
Step 4: Outlier Detection and Handling
IQR Method
Q1 = df['amount'].quantile(0.25)
Q3 = df['amount'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Option A: Filter (remove outlier rows)
df = df[(df['amount'] >= lower_bound) & (df['amount'] <= upper_bound)]
# Option B: Cap with [Link] (PREFERRED - preserves all rows)
import numpy as np
df['amount'] = [Link](df['amount'], lower_bound, upper_bound)
✅ Prefer [Link]() over filtering. Capping replaces extreme values with boundary values
while KEEPING all rows. Filtering discards rows which may contain other useful data.
Step 5: Automating the Cleaning Pipeline
for col in [Link]:
if df[col].dtype == 'object': # categorical
df[col].fillna('unknown', inplace=True)
else: # numerical
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# Skip binary columns
if df[col].dropna().isin([0, 1]).all():
pass
else:
df[col].fillna(df[col].median(), inplace=True)
Situation Recommended Action
Few missing values, large dataset Drop rows
Numerical, symmetric distribution Fill with mean
Numerical, extreme Fill with median
observations/skewed
Categorical, clear dominant value Fill with mode (cautiously)
Categorical, no clear majority Fill with 'unknown'
Column has 60%+ missing values Consider dropping entire column
Column has one value 99% of the Consider dropping (no useful pattern)
time
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 8.2
Exploratory Data Analysis (EDA) Concepts
Turning data into visual insights with Matplotlib
IM Resources: Click here to access interactive module resources
Learning Objectives
• Explain what EDA is and where it fits in the data workflow
• Identify the three types of analysis — univariate, bivariate, multivariate — and match to the right
chart
• Build eight core chart types using Matplotlib
• Apply correlation to measure relationship strength between numerical variables
Key principle: EDA is a thinking problem first and a coding problem second. Pandas proficiency
comes before visualization — summarize large data with groupby/aggregations before plotting.
Three Types of Analysis
Analysis Type Variables Example Charts
Univariate 1 variable Histogram, Box plot, Pie chart, Violin plot
Bivariate 2 variables Scatter plot, Line chart, Bar chart
Multivariate 3+ variables Bubble chart, Heat map, Pair plot
General Matplotlib Syntax
import [Link] as plt
[Link](figsize=(10, 6)) # set canvas size
[Link](...) # chart-specific call
[Link]('My Chart')
[Link]('X axis label')
[Link]('Y axis label')
[Link]()
Eight Core Chart Types
Chart 1: Histogram (Univariate — Distribution)
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Shows how often values fall into each range. Use to understand distribution, check for data bias,
examine spread.
[Link](figsize=(8, 5))
[Link](df['salary'], bins=10)
[Link]('salary')
[Link]('frequency')
[Link]('Distribution of Salary')
[Link]()
Chart 2: Box Plot (Univariate — Spread & Outliers)
Shows distribution, spread, and outliers. Key elements: median (orange line), Q1/Q3 (box edges), IQR
(box), whiskers (1.5 × IQR), outlier dots.
[Link](df['salary'])
[Link]()
Chart 3: Line Chart (Bivariate — Trends Over Time)
months = ['January', 'February', 'March', 'April', 'May']
sales = [12000, 14000, 13500, 15000, 16500]
[Link](months, sales)
[Link]('Monthly Sales Trend')
[Link]()
Chart 4: Scatter Plot (Bivariate — Relationship)
[Link](df['experience'], df['salary'])
[Link]('experience')
[Link]('salary')
[Link]('Experience vs Salary')
[Link]()
Chart 5: Bar Chart (Bivariate — Comparison by Category)
Important: Always aggregate with Pandas first, then plot.
avg_salary = [Link]('department')['salary'].mean().reset_index()
[Link](avg_salary['department'], avg_salary['salary'])
[Link]('Average Salary by Department')
[Link]()
Chart 6: Pie Chart (Univariate — Proportions)
dept_counts = df['department'].value_counts()
[Link](dept_counts.values,
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
labels=dept_counts.index,
autopct='%1.1f%%')
[Link]('Department Distribution')
[Link]()
Chart 7: Violin Plot (Univariate — Distribution Shape)
Extends box plot by adding the shape of the distribution. Wider parts = more observations concentrated
there.
[Link](df['salary'])
[Link]('Salary Distribution (Violin)')
[Link]()
Chart 8: Bubble Chart (Multivariate — 4 variables)
[Link](
df['experience'],
df['salary'],
s=df['age'], # bubble SIZE encodes age
c=df['department'].map({'HR':'blue','IT':'red','Finance':'green'}) # COLOR
)
[Link]('Experience vs Salary (bubble=age, color=dept)')
[Link]()
Correlation
# Pearson correlation matrix for all numerical columns
cor = df[['age','salary','experience']].corr()
print(cor)
# Values: +1 = perfect positive, -1 = perfect negative, 0 = no relationship
Chart Analysis Type Best For
Histogram Univariate Distribution of a numerical variable
Box plot Univariate Spread and outliers
Violin plot Univariate Distribution shape
Pie chart Univariate Proportions across categories
Line chart Bivariate Trends over time
Scatter plot Bivariate Relationship between two numerical variables
Bar chart Bivariate Comparing values across categories
Bubble chart Multivariate Encoding 4 variables at once
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Session 8.3
Visualizing Data with Seaborn
Statistical charts with less code and better defaults
IM Resources: Click here to access interactive module resources
Learning Objectives
• Explain what Seaborn is and why it produces cleaner charts than raw Matplotlib
• Apply Seaborn syntax to create eleven chart types for distribution, relationship, and comparison
• Combine Seaborn and Matplotlib calls in the same cell
• Build multi-chart layouts using subplots
Matplotlib vs Seaborn Syntax
# Matplotlib: pass raw arrays
[Link](df['salary'], df['experience'])
# Seaborn: pass column name strings + DataFrame
[Link](x='salary', y='experience', data=df)
# Always import both
import [Link] as plt
import seaborn as sns
💡 Common Mistakes: (1) Passing raw arrays instead of column name strings. (2) Forgetting
data=df. (3) Forgetting to import Matplotlib alongside Seaborn — [Link]() and [Link]() still
come from Matplotlib.
The 11 Seaborn Chart Types
1. Histogram — [Link]
[Link](data=df, x='salary', bins=5)
[Link]('Distribution of Salary')
[Link]()
2. Box Plot — [Link]
# Univariate
[Link](data=df, x='salary')
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# Bivariate: one box per department
[Link](data=df, x='salary', y='department')
3. Scatter Plot — [Link]
[Link](data=df, x='salary', y='experience')
4. Bubble Chart — scatterplot with hue and size
[Link](data=df, x='salary', y='experience',
hue='department', # color by category (auto!)
size='age') # dot size by numeric value
[Link](loc='upper left')
5. Line Plot — [Link]
[Link](data=df, x='experience', y='salary',
marker='o', # dot at each data point
linestyle='--') # dashed line
6. Bar Plot — [Link]
# Default: mean salary per department
[Link](data=df, x='department', y='salary')
# Custom aggregation
import numpy as np
[Link](data=df, x='department', y='salary', estimator=[Link])
7. Count Plot — [Link]
# Counts rows per category (no y argument needed)
[Link](data=df, x='department')
# Seaborn-specific: no direct Matplotlib equivalent
8. Violin Plot — [Link]
# Shows distribution shape + spread per category
[Link](data=df, x='department', y='salary')
9. Pair Plot — [Link]
# Grid of scatter plots for all pairs + histograms on diagonal
[Link](df[['salary','experience','age']])
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
# Only pass the columns you need - too many = visual noise
10. Heat Map — [Link]
# Step 1: compute correlation matrix
corr = [Link](numeric_only=True)
# Step 2: visualize
[Link](corr,
annot=True, # show numeric values in cells
cmap='coolwarm') # red=positive, blue=negative
11. Joint Plot — [Link]
# Scatter plot + marginal histograms in one figure
[Link](data=df, x='experience', y='salary')
Subplots — Multiple Charts in One Figure
# 1 row, 2 columns
fig, ax = [Link](1, 2, figsize=(10, 4))
df['salary'].hist(ax=ax[0])
df['salary'].plot(kind='box', ax=ax[1])
[Link]()
# 2x2 grid
fig, ax = [Link](2, 2, figsize=(10, 8))
df['salary'].hist(ax=ax[0, 0])
df['salary'].plot(kind='box', ax=ax[0, 1])
[Link](data=df, x='experience', y='salary', ax=ax[1, 0])
[Link](data=df, x='department', y='salary', ax=ax[1, 1])
[Link]()
Chart Function Best For
Histogram [Link] Distribution of a numerical variable
Box Plot [Link] Spread and outliers per category
Scatter Plot [Link] Relationship between two numerical vars
Bubble Chart [Link] + hue/size Encoding 3–4 variables
Line Plot [Link] Trends over ordered/time variable
Bar Plot [Link] Aggregated value per category (mean by default)
Count Plot [Link] Row count per category
AI & Machine Learning ProgramPage
Module 2 Compiled Lecture Notes | IITREICT-DSAI-2603 |
Violin Plot [Link] Distribution shape per category
Pair Plot [Link] All pairwise relationships at once
Heat Map [Link] Correlation matrix visualization
Joint Plot [Link] Scatter + marginal distributions
🧠 Mental model: Seaborn is a smart layer on top of Matplotlib. You describe WHAT you
want to see — the chart type and the columns — and Seaborn handles repetitive formatting
for you. Note: Seaborn has NO pie chart. Use [Link]() from Matplotlib.
AI & Machine Learning ProgramPage