0% found this document useful (0 votes)
5 views44 pages

Module2 Compiled Lecture Notes

Module 2 of the AI & Machine Learning Program at IITREICT-DSAI-2603 covers key topics in data manipulation using NumPy and Pandas, including array creation, vectorized operations, data cleaning, and exploratory data analysis. The module emphasizes efficient data processing techniques and best practices, highlighting the performance benefits of using NumPy over traditional Python lists. Interactive resources are provided for deeper learning and practical application of the concepts discussed.

Uploaded by

bhumiraghav04
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views44 pages

Module2 Compiled Lecture Notes

Module 2 of the AI & Machine Learning Program at IITREICT-DSAI-2603 covers key topics in data manipulation using NumPy and Pandas, including array creation, vectorized operations, data cleaning, and exploratory data analysis. The module emphasizes efficient data processing techniques and best practices, highlighting the performance benefits of using NumPy over traditional Python lists. Interactive resources are provided for deeper learning and practical application of the concepts discussed.

Uploaded by

bhumiraghav04
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

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

You might also like