UT Austin | Great Learning PGP in AI & ML
Every concept explained from scratch. No assumptions. Real-life examples for everything.
Notes prepared by: Vamshi Krishan Reddy Bandaru
β‘ Cheat Sheet
πΊοΈ Concept Map
π» 1.1 Colab & Setup
π€ 1.2 Variables
π¦ 1.3 Data Structures
π 1.4 Control Flow
βοΈ 1.5 Functions
π’ 2.1 NumPy
πΌ 2.2 Pandas
π§Ή 2.3 Data Cleaning
π 3.1 Visualization
π 3.2 EDA Techniques
π 4.1 Text Analysis
β οΈ Mistakes
β‘ Python Foundations Cheat Sheet
Big Picture
This module covers Python from zero to data analysis. Four weeks of building blocks:
Week 1: Python basics β variables, data structures, loops, functions
Week 2: Data manipulation β NumPy arrays and Pandas DataFrames
Week 3: Exploratory Data Analysis β visualization and statistical insights
Week 4: Text analysis β string processing, regex, basic NLP
Build the foundation β learn to think in Python. Every data science workflow starts here.
π¬
Videos 1.1-1.3: Google Colab setup β your free cloud coding environment. Markdown cells for documentation, code cells for execution.
π¬
Videos 1.4-1.6: Variables and type conversion β the building blocks. Python is dynamically typed, so x = 5 then x = "hello" is perfectly valid.
π¬
Videos 1.7-1.9: Data structures β lists (mutable, ordered), tuples (immutable, ordered), dictionaries (key-value pairs). The trio you will use in every project.
π¬
Videos 1.10-1.12: Control flow β conditionals (if/elif/else) and loops (for, while). The logic engine of every program.
π¬
Videos 1.13-1.15: List comprehension and functions β writing clean, reusable, Pythonic code. Lambda functions for quick one-liners.
Week 2: Data Manipulation (18 Videos)
Move from basic Python to data science tools. NumPy for numerical computing, Pandas for structured data.
π
NumPy: Fast numerical operations on arrays. Broadcasting, vectorized operations, and mathematical functions that work on entire arrays at once.
πΌ
Pandas: The Swiss Army knife of data manipulation. Read CSV files, explore with head()/describe(), filter with boolean indexing, aggregate with groupby().
π§Ή
Data Cleaning: Handle missing values (isnull, dropna, fillna), fix data types, merge datasets, and prepare data for analysis.
Week 3: Exploratory Data Analysis (16 Videos)
Turn raw data into visual insights. Learn to see patterns, detect outliers, and tell stories with data.
π
Matplotlib: The foundation of Python plotting. Figures, axes, subplots, and full customization control.
π¨
Seaborn: Beautiful statistical visualizations built on Matplotlib. Heatmaps, pair plots, distribution plots with minimal code.
π
Statistical measures: mean, median, mode, variance, standard deviation, IQR for outlier detection, correlation for relationships.
Week 4: Analyzing Text Data (5 Videos)
Text is data too. Learn to process, clean, and extract insights from unstructured text.
π
String methods, regular expressions, tokenization, and word frequency analysis β the basics of Natural Language Processing.
π» 1.1 Google Colab & Python Setup
Week 1
Google Colab (Colaboratory)
A free, cloud-based Jupyter notebook environment by Google. Write and execute Python code in your browser β no installation required. Comes with free GPU/TPU access for machine learning.
Like Google Docs, but for code. Multiple people can edit the same notebook simultaneously, and everything saves to Google Drive.
Jupyter Notebook (.ipynb)
An interactive document format that combines code, text, and visualizations in a single file. The .ipynb extension stands for "IPython Notebook." Colab uses this format natively.
A scientist's lab notebook β you write observations (Markdown), run experiments (code cells), and see results (outputs) all in one place.
Markdown Cell
A cell in Colab for writing formatted text using Markdown syntax. Use # for headings, **bold** for bold, *italic* for italic, and - for bullet points.
The table of contents and chapter headers in your lab notebook β they organize and explain your work.
Think of Google Colab as a free cooking show kitchen. The stove (Python engine) is already set up, the ingredients (libraries like NumPy, Pandas) are pre-stocked, and you just need to follow the recipe (write code). You do not need to buy any equipment or install anything β just show up and start cooking.
Colab Notebook Structure
Notebook (.ipynb)
β
Markdown Cells (Text + Formatting)
Code Cells (Python Execution)
β
Output (Results, Charts, Tables)
Getting Started Steps
1
Go to colab.research.google.com and sign in with your Google account.
2
Click "New Notebook" β a fresh .ipynb file opens connected to a cloud Python runtime.
3
Type Python code in a code cell and press Shift + Enter to execute. The output appears below the cell.
4
Add a text cell (Insert β Text cell) to write notes using Markdown formatting.
5
Save your work: it auto-saves to Google Drive. Download via File β Download β Download .ipynb.
Essential Keyboard Shortcuts
Shortcut
Action
When to Use
Shift + Enter
Run cell and move to next
Execute code and continue
Ctrl + Enter
Run cell, stay in place
Test code without moving
Ctrl + M, B
Insert cell below
Add new code/text cell
Ctrl + M, D
Delete current cell
Remove unwanted cells
Ctrl + M, M
Convert to Markdown
Switch cell type to text
Ctrl + M, Y
Convert to Code
Switch cell type to code
Ctrl + /
Toggle comment
Comment/uncomment lines
# Your very first Python code in Colabprint("Hello, World!") # Output: Hello, World!# Python is case-sensitive!Name = "Alice"name = "Bob"print(Name) # Aliceprint(name) # Bob β these are DIFFERENT variables# Comments: # for single-line, triple quotes for multi-line'''
This is a multi-line comment.
It can span several lines.
Useful for documentation.
'''
β οΈ
Python is case-sensitive!HelloWorld and helloworld are completely different. This is one of the most common beginner mistakes (FAQ #2 from the course).
Test Your Understanding
Q: How do you download a Colab notebook to your computer?
Q: What happens if you write Print("Hello") instead of print("Hello")?
π€ 1.2 Variables & Data Types
Week 1
Variable
A named container that stores a value in memory. In Python, you create a variable simply by assigning a value: x = 10. No need to declare the type β Python figures it out automatically (dynamic typing).
A labeled jar in your kitchen. The label says "sugar" (variable name), and inside is the actual sugar (the value). You can empty it and fill it with salt later β the jar does not care what is inside.
Dynamic Typing
Python determines the type of a variable at runtime based on the value assigned. You can reassign a variable to a completely different type without errors. Use type(x) to check the current type.
A parking spot that accepts any vehicle β car, motorcycle, or truck. The spot does not need a sign saying "cars only."
Type Conversion (Casting)
Explicitly changing a value from one type to another using functions like int(), float(), str(), bool(). Essential when combining different types β you cannot concatenate a string and an integer directly.
Converting currency β changing US dollars to Euros. The value stays the same in principle, but the format changes so it can be used in a different context.
Variables are like phone contacts. The contact name ("Mom") is the variable name, and the phone number (555-1234) is the value. You can update the number anytime, and the name still works. You can even change "Mom" to store an email address instead of a phone number β Python does not mind.
Python Data Types
Type
Description
Example
Check With
int
Whole numbers (no decimal)
x = 42
type(42) β <class 'int'>
float
Decimal numbers
pi = 3.14
type(3.14) β <class 'float'>
str
Text (string of characters)
name = "Alice"
type("hi") β <class 'str'>
bool
True or False
is_valid = True
type(True) β <class 'bool'>
NoneType
Absence of value
x = None
type(None) β <class 'NoneType'>
int32 vs int64 (FAQ #8)
When working with NumPy and Pandas, you will encounter int32 and int64:
int32: Uses 4 bytes (32 bits) of memory. Range: -2,147,483,648 to 2,147,483,647
int64: Uses 8 bytes (64 bits) of memory. Range: approximately -9.2 Γ 10ΒΉβΈ to 9.2 Γ 10ΒΉβΈ
For most data science work, int64 is the default and perfectly fine. Only optimize to int32 when memory is a constraint with large datasets.
TypeError: can only concatenate str to str. This is one of the most common Python errors (FAQ #14). Fix it by converting the number to a string with str() or by using f-strings: f"value is {x}".
Test Your Understanding
Q: What does type(42) return in Python?
Q: What is the result of 9 // 5?
π¦ 1.3 Data Structures: Lists, Tuples, Dictionaries
Week 1
List
A mutable, ordered collection of items enclosed in square brackets []. Lists can hold mixed types (integers, strings, booleans, even other lists). Created with list() or [].
A shopping list on paper β you can add items, cross them off, rearrange them, and they stay in order.
Tuple
An immutable, ordered collection enclosed in parentheses (). Once created, you cannot add, remove, or modify elements. Created with tuple() or ().
A sealed time capsule β once you put items in and seal it, you can look at the contents but cannot change them.
Dictionary
A mutable, unordered collection of key-value pairs enclosed in curly braces {}. Access values by their unique key, not by position. Created with dict() or {}.
A real dictionary book β you look up a word (key) to find its definition (value). You do not search by page number.
A list is a shelf with numbered slots β items stay in order, you can swap them. A tuple is a display case with a glass cover β look but do not touch. A dictionary is a filing cabinet β each drawer has a label (key), inside is the content (value).
Comparison: List vs Tuple vs Dictionary (FAQ #5)
Feature
List
Tuple
Dictionary
Syntax
[1, 2, 3]
(1, 2, 3)
{"a": 1}
Mutable?
Yes β can add/remove/change
No β immutable
Yes β can add/remove/change
Ordered?
Yes β maintains insertion order
Yes β maintains insertion order
Yes (Python 3.7+)
Access By
Index: lst[0]
Index: tpl[0]
Key: dct["key"]
Duplicates?
Allowed
Allowed
Keys must be unique
Use Case
Dynamic collections
Fixed data (coordinates, constants)
Lookups, mappings
Constructor
list()
tuple()
dict()
Bracket Guide (FAQ #6)
One of the most confusing things for beginners β which bracket for what?
# ============ LISTS ============fruits = ["apple", "banana", "cherry"]
print(fruits[0]) # "apple" β indexing starts at 0print(fruits[-1]) # "cherry" β negative index = from endfruits.append("date") # Add to end: ["apple","banana","cherry","date"]fruits.remove("banana") # Remove by valuefruits.insert(1, "fig") # Insert at index 1print(len(fruits)) # 3 β number of items# Slicing: list[start:stop:step]nums = [0, 1, 2, 3, 4, 5]
print(nums[1:4]) # [1, 2, 3] β start inclusive, stop exclusiveprint(nums[:3]) # [0, 1, 2] β from beginningprint(nums[3:]) # [3, 4, 5] β to endprint(nums[::2]) # [0, 2, 4] β every 2nd element# ============ TUPLES ============coords = (10.5, 20.3)
print(coords[0]) # 10.5# coords[0] = 99 # TypeError! Tuples are immutable# ============ DICTIONARIES ============student = {
"name": "Vamshi",
"age": 25,
"courses": ["Python", "ML"]
}
print(student["name"]) # "Vamshi" β access by key (FAQ #7)student["grade"] = "A"# Add new key-value pairprint(student.keys()) # dict_keys(['name', 'age', 'courses', 'grade'])print(student.values()) # dict_values(['Vamshi', 25, ['Python', 'ML'], 'A'])
Indexing Visual β How Python Counts
0
1
2
3
4
["a", "b", "c", "d", "e"] β Forward index (0 to n-1)
-5
-4
-3
-2
-1
Negative index β counts from the end
Common List Methods
Method
What It Does
Example
.append(x)
Add x to end
[1,2].append(3) β [1,2,3]
.insert(i, x)
Insert x at index i
[1,3].insert(1,2) β [1,2,3]
.remove(x)
Remove first occurrence of x
[1,2,2].remove(2) β [1,2]
.pop(i)
Remove & return item at index i
[1,2,3].pop(0) β 1
.sort()
Sort in place (ascending)
[3,1,2].sort() β [1,2,3]
.reverse()
Reverse in place
[1,2,3].reverse() β [3,2,1]
.index(x)
Find index of first x
[10,20,30].index(20) β 1
.count(x)
Count occurrences of x
[1,1,2].count(1) β 2
.extend(lst)
Add all items from another list
[1].extend([2,3]) β [1,2,3]
Test Your Understanding
Q: Which data structure uses curly braces {} and stores key-value pairs?
Q: What happens when you try my_tuple[0] = "new" on an existing tuple?
π 1.4 Control Flow: Conditionals & Loops
Week 1
Conditional Statement (if/elif/else)
A control structure that executes different blocks of code based on whether a condition is True or False. Python uses indentation (4 spaces) to define code blocks β no curly braces like other languages.
A traffic light β if green, go. Elif (else if) yellow, slow down. Else (red), stop. Only one action happens based on the current state.
For Loop
Iterates over a sequence (list, tuple, string, range) executing a block of code for each element. The variable i (or any name you choose) takes on each value in the sequence, one at a time (FAQ #13).
A postal worker delivering mail β they visit each house on the street in order, drop off the mail, then move to the next house.
While Loop
Repeats a block of code as long as a condition remains True. Be careful β if the condition never becomes False, you get an infinite loop! Always make sure the condition will eventually change (FAQ #12).
Filling a bathtub β keep the water running WHILE the tub is not full. Once it is full, stop. If you forget to check, the water overflows (infinite loop).
Control flow is like a choose-your-own-adventure book. At each decision point (if), you pick a path. For loops know how many times to repeat; while loops keep going until a condition changes.
Q: What keyword skips the current iteration and moves to the next one?
βοΈ 1.5 Functions & List Comprehension
Week 1
Function
A reusable block of code that performs a specific task. Defined with the def keyword, it can accept inputs (parameters) and return outputs. Functions eliminate code duplication and make programs modular.
A coffee machine β you put in water and beans (inputs), press a button (call the function), and get coffee (output). You do not need to know how the machine works internally to use it.
Return Statement
Sends a value back from a function to the caller. Without return, the function returns None by default. A function can return multiple values as a tuple: return a, b.
A vending machine β you insert money (arguments), the machine processes your selection, and returns the snack to you. If you just press buttons without inserting money, you get nothing (None).
Lambda Function
An anonymous, one-line function defined with the lambda keyword. Syntax: lambda arguments: expression. Best for simple operations where defining a full function would be overkill.
A sticky note with a quick formula β instead of writing a full instruction manual, you jot down "multiply by 2" on a Post-it and stick it where needed.
List Comprehension
A concise, Pythonic way to create lists in a single line. Syntax: [expression for item in iterable if condition]. It replaces multi-line for loops with a compact, readable expression.
A factory assembly line β raw materials (iterable) come in, each gets processed (expression), and defective ones are filtered out (condition). The output is a list of finished products.
Functions are recipes in a cookbook β define once, call by name whenever needed. Lambda functions are quick recipes on a napkin. List comprehensions are speed-cooking: make 10 dishes at once in one instruction.
Pythonic Code: List comprehensions are considered more "Pythonic" than equivalent for loops. They are also slightly faster because the loop happens internally in C. Use them for simple transformations. For complex logic, stick with regular for loops for readability.
Test Your Understanding
Q: What does [x*2 for x in [1,2,3] if x > 1] return?
π’ 2.1 NumPy: Numerical Computing
Week 2
NumPy (Numerical Python)
A fundamental Python library for numerical computing. Its core object is the ndarray (N-dimensional array), which enables fast mathematical operations on large datasets. NumPy is the foundation upon which Pandas, scikit-learn, and most data science libraries are built.
A calculator that can handle millions of numbers at once. Instead of adding numbers one by one in a loop, NumPy adds entire arrays in a single operation β like having a million calculators working simultaneously.
Vectorized Operations
Operations that apply to entire arrays at once, without explicit loops. NumPy executes these in optimized C code, making them 10-100x faster than Python loops. Examples: arr * 2, arr1 + arr2, np.sqrt(arr).
A factory production line that stamps all parts at once, vs. a craftsman filing each part individually.
Broadcasting
NumPy's ability to perform operations on arrays of different shapes by automatically expanding the smaller array to match. For example, adding a scalar to an array or adding a 1D array to each row of a 2D array.
Giving a $5 raise to every employee in a company. You state the raise once, and it "broadcasts" to everyone's salary β you do not need to write each person's new salary individually.
Think of Python lists as a regular backpack β flexible, can hold anything, but slow to search through. NumPy arrays are like an organized toolbox β everything has a fixed type and position, so finding and using tools is lightning fast. The trade-off: the toolbox only holds one type of item (all integers, all floats, etc.), but it is extremely efficient.
Q: What is the main advantage of NumPy arrays over Python lists for numerical data?
πΌ 2.2 Pandas: Data Manipulation
Week 2
Pandas
The most popular Python library for data manipulation and analysis. It provides two primary data structures: Series (1D labeled array) and DataFrame (2D labeled table with rows and columns). Think of a DataFrame as a supercharged Excel spreadsheet that you can program.
Excel on steroids β you can load a million-row CSV file, filter it, group it, merge it with another file, and compute statistics, all in a few lines of code.
DataFrame
A 2D labeled data structure with named columns and an index. Each column is a Pandas Series. Created from dictionaries, CSV files, Excel files, or SQL queries. The workhorse of data science in Python.
A database table or Excel spreadsheet β rows are individual records (customers, transactions), columns are attributes (name, age, purchase amount).
Boolean Indexing
Filtering rows in a DataFrame using a condition that returns True/False for each row. Syntax: df[df['column'] > value]. You can combine conditions with & (and) and | (or).
Telling a librarian "Show me only the books published after 2020 that are science fiction" β the librarian checks each book and hands you only the matching ones.
Pandas is like hiring a personal assistant for your data. You say "read this CSV file" (pd.read_csv), "show me the first few rows" (.head()), "what are the stats?" (.describe()), "group by department and give me averages" (.groupby().mean()). The assistant does all the tedious work instantly.
import pandas as pd
# Creating a DataFrame from a dictionarydata = {
"Name": ["Alice", "Bob", "Charlie", "Diana"],
"Age": [25, 30, 35, 28],
"Salary": [50000, 60000, 75000, 55000]
}
df = pd.DataFrame(data)
# Reading from a CSV filedf = pd.read_csv("employees.csv")
# First look at data β the essential 5print(df.head()) # First 5 rowsprint(df.tail()) # Last 5 rowsprint(df.shape) # (rows, columns)print(df.info()) # Column types, non-null countsprint(df.describe()) # Summary statistics# Selecting columnsprint(df["Name"]) # Single column β Seriesprint(df[["Name", "Age"]]) # Multiple columns β DataFrame# Selecting rows: loc (label-based) vs iloc (integer-based)print(df.loc[0]) # First row by labelprint(df.iloc[0:3]) # First 3 rows by position# Boolean indexing β filteringseniors = df[df["Age"] > 30]
high_earners = df[(df["Salary"] > 55000) & (df["Age"] < 35)]
# Sortingdf_sorted = df.sort_values("Salary", ascending=False)
# Groupby β split-apply-combinedept_avg = df.groupby("Department")["Salary"].mean()
# Adding new columnsdf["Bonus"] = df["Salary"] * 0.1# Apply custom functiondf["Category"] = df["Age"].apply(lambdax: "Senior"ifx > 30else"Junior")
Essential Pandas Methods
Method
Purpose
Example
.head(n)
First n rows
df.head(10)
.describe()
Summary statistics
df.describe()
.value_counts()
Frequency of values
df["City"].value_counts()
.groupby()
Group and aggregate
df.groupby("Dept").mean()
.sort_values()
Sort by column
df.sort_values("Age")
.merge()
Join two DataFrames
pd.merge(df1, df2, on="ID")
.concat()
Stack DataFrames
pd.concat([df1, df2])
.apply()
Apply function to column
df["Col"].apply(func)
.unique()
Unique values
df["City"].unique()
.nunique()
Count of unique values
df["City"].nunique()
GroupBy: Split β Apply β Combine
Original DataFrame
β .groupby("Department")
Group: Sales
Group: Engineering
Group: Marketing
β .mean() / .sum() / .count()
Aggregated Result per Group
Test Your Understanding
Q: How do you select rows where the "Age" column is greater than 30?
π§Ή 2.3 Data Cleaning & Preparation
Week 2
Missing Values (NaN)
Entries in your dataset that have no value. Represented as NaN (Not a Number) in Pandas. Can occur due to data entry errors, sensor failures, or optional fields. Must be handled before analysis because they propagate through calculations.
Blank cells in a spreadsheet β some customers did not fill in their phone number. You cannot compute an "average phone number," so you must decide: fill in a default, remove those rows, or ignore that column.
Data Type Conversion
Changing the data type of a column to the appropriate type. Common conversions: string to datetime, object to category, string to numeric. Use df['col'].astype() or pd.to_datetime(), pd.to_numeric().
Converting currency strings like "$1,500.00" to the number 1500.0 so you can do math with them.
Data cleaning is like preparing ingredients before cooking. You wash vegetables (remove duplicates), peel and chop them (type conversion), and check for any rotten pieces (missing values). No chef starts cooking with dirty, unprepped ingredients β and no data scientist starts analyzing dirty data.
import pandas as pd
import numpy as np
# ============ MISSING VALUES ============# Detect missing valuesprint(df.isnull().sum()) # Count NaN per columnprint(df.isnull().sum() / len(df) * 100) # Percentage missing# Strategy 1: Drop rows with any NaNdf_clean = df.dropna()
# Strategy 2: Drop columns with too many NaNdf_clean = df.dropna(axis=1, thresh=len(df)*0.5) # Keep cols with >50% data# Strategy 3: Fill missing valuesdf["Age"].fillna(df["Age"].mean(), inplace=True) # Fill with meandf["City"].fillna("Unknown", inplace=True) # Fill with constantdf["Score"].fillna(df["Score"].median(), inplace=True) # Median for skewed data# ============ DUPLICATES ============print(df.duplicated().sum()) # Count duplicate rowsdf_clean = df.drop_duplicates() # Remove duplicates# ============ TYPE CONVERSION ============df["Date"] = pd.to_datetime(df["Date"])
df["Price"] = pd.to_numeric(df["Price"], errors="coerce")
# ============ STRING CLEANING ============df["Name"] = df["Name"].str.strip() # Remove whitespacedf["Name"] = df["Name"].str.lower() # Lowercasedf["Email"] = df["Email"].str.replace("@old.com", "@new.com")
# ============ MERGING DATASETS ============merged = pd.merge(df1, df2, on="CustomerID", how="left")
stacked = pd.concat([df_2023, df_2024], ignore_index=True)
Missing Value Strategy Decision Guide
Scenario
Strategy
Code
Very few missing (<5%)
Drop rows
df.dropna()
Numerical, normally distributed
Fill with mean
df["col"].fillna(df["col"].mean())
Numerical, skewed
Fill with median
df["col"].fillna(df["col"].median())
Categorical
Fill with mode
df["col"].fillna(df["col"].mode()[0])
Column >50% missing
Drop column
df.drop("col", axis=1)
Time series
Forward/backward fill
df["col"].fillna(method="ffill")
Test Your Understanding
Q: Which method counts the number of missing values per column?
π 3.1 Data Visualization
Week 3
Matplotlib
The foundational Python plotting library. Provides complete control over every element of a figure: axes, labels, colors, sizes, legends. Most other Python visualization libraries (including Seaborn) are built on top of Matplotlib.
A blank canvas with all the paint colors β you can create any visualization, but you must specify every detail yourself.
Seaborn
A statistical visualization library built on Matplotlib. Provides beautiful, informative plots with minimal code. Especially good for showing distributions, relationships, and categorical comparisons.
A paint-by-numbers kit β you get professional-looking results with much less effort. Perfect for statistical plots.
Matplotlib is like cooking from scratch β full control, but you do everything yourself. Seaborn is like using a meal kit β pre-measured ingredients, beautiful presentation, and it still tastes great. Most data scientists use both: Seaborn for quick statistical plots, Matplotlib for custom fine-tuning.
Chart Selection Guide
Question
Chart Type
Code
Distribution of one variable?
Histogram / KDE
sns.histplot(df["Age"])
Relationship between two numeric?
Scatter plot
plt.scatter(x, y)
Comparison across categories?
Bar chart
sns.countplot(x="City", data=df)
Spread and outliers?
Box plot
sns.boxplot(x="Dept", y="Salary")
Correlation between all pairs?
Heatmap
sns.heatmap(df.corr())
Trend over time?
Line chart
plt.plot(dates, values)
All pairwise relationships?
Pair plot
sns.pairplot(df)
Proportions of a whole?
Pie chart
plt.pie(sizes, labels=labels)
import matplotlib.pyplot as plt
import seaborn as sns
# ============ MATPLOTLIB BASICS ============# Simple line plotfig, ax = plt.subplots(figsize=(10, 6))
ax.plot([1,2,3,4], [10,20,25,30], marker='o')
ax.set_xlabel("Quarter")
ax.set_ylabel("Revenue ($K)")
ax.set_title("Quarterly Revenue")
plt.show()
# Multiple subplotsfig, axes = plt.subplots(1, 3, figsize=(15, 5))
axes[0].hist(df["Age"], bins=20)
axes[1].scatter(df["Age"], df["Salary"])
axes[2].boxplot(df["Salary"])
plt.tight_layout()
plt.show()
# ============ SEABORN ============# Distribution plot
sns.histplot(df["Age"], kde=True, bins=20)
# Correlation heatmap
plt.figure(figsize=(10, 8))
sns.heatmap(df.corr(), annot=True, cmap="coolwarm", vmin=-1, vmax=1)
# Box plot for comparing groups
sns.boxplot(x="Department", y="Salary", data=df)
# Pair plot β all relationships at once
sns.pairplot(df, hue="Category")
Test Your Understanding
Q: Which plot is best for showing the correlation between all numerical variables at once?
π 3.2 EDA Techniques & Statistics
Week 3
Exploratory Data Analysis (EDA)
A systematic approach to investigating datasets using summary statistics and visualizations before formal modeling. The goal is to discover patterns, spot anomalies, test hypotheses, and check assumptions. John Tukey coined the term in 1977.
A detective examining a crime scene β before forming theories, you observe everything: what is there, what is missing, what looks unusual, what patterns emerge.
Outlier
A data point that lies significantly outside the overall pattern of the data. Can be detected using the IQR method (below Q1-1.5ΓIQR or above Q3+1.5ΓIQR) or Z-score (more than 3 standard deviations from the mean). May indicate errors, fraud, or genuinely extreme values.
In a classroom of 30 students with ages 18-22, one "student" listed as age 97 is clearly an outlier β likely a data entry error.
Correlation
A statistical measure (-1 to +1) of the linear relationship between two variables. +1 means perfect positive correlation, -1 means perfect negative, 0 means no linear relationship. Calculated with df.corr(). Remember: correlation does not imply causation.
Ice cream sales and drowning deaths are positively correlated β not because ice cream causes drowning, but because both increase in summer (confounding variable: hot weather).
EDA is like a doctor doing a checkup β take vital signs (summary stats), look at X-rays (visualizations), check for symptoms (outliers), and run blood tests (correlations) before diagnosing (modeling).
EDA Checklist
1
Shape & Structure:df.shape, df.info(), df.dtypes β How big is the data? What types are the columns?
2
Summary Statistics:df.describe() β Mean, median, min, max, quartiles for every numerical column.
3
Missing Values:df.isnull().sum() β Which columns have gaps? How much data is missing?
4
Univariate Analysis: Histograms and box plots for each variable individually β What does each variable look like?
5
Bivariate Analysis: Scatter plots, grouped bar charts β How do variables relate to each other?
6
Correlation Analysis:sns.heatmap(df.corr()) β Which variables move together?
7
Outlier Detection: IQR method or Z-scores β Are there extreme values that need attention?
Statistical Measures Quick Reference
Central Tendency
Mean:df["col"].mean() β average, sensitive to outliers Median:df["col"].median() β middle value, robust to outliers Mode:df["col"].mode() β most frequent value
Spread / Dispersion
Std Dev:df["col"].std() β average distance from mean Variance:df["col"].var() β std dev squared IQR: Q3 - Q1 β spread of middle 50% Range: max - min β total spread
Q: If a dataset has a few extreme high values, which measure of central tendency is more reliable?
π 4.1 Analyzing Text Data
Week 4
Regular Expression (Regex)
A powerful pattern-matching language for searching, extracting, and manipulating text. Python provides the re module. Common patterns: \d (digit), \w (word character), \s (whitespace), . (any character), * (0 or more), + (1 or more).
A metal detector on a beach β you define what you are looking for (pattern), and the regex engine scans through the entire text to find all matches.
Tokenization
The process of splitting text into individual units (tokens), typically words or sentences. The first step in most text analysis pipelines. Can be done with .split() for simple cases or with NLP libraries for complex text.
Breaking a sentence into individual words β like taking apart a LEGO structure into its individual bricks before sorting and counting them.
Stop Words
Common words (the, is, at, which, on) that carry little meaningful information and are typically removed during text preprocessing. Removing them reduces noise and improves analysis quality.
In a book review, words like "the," "is," and "was" appear everywhere but tell you nothing about whether the reviewer liked the book. The meaningful words are "excellent," "boring," "recommended."
Text analysis is like being a librarian organizing documents: break into words (tokenization), ignore filler words (stop word removal), count important words (frequency analysis), and use patterns to find specific info like phone numbers (regex).
import re
# ============ STRING METHODS ============text = " Hello, World! Welcome to Python. "print(text.strip()) # Remove leading/trailing whitespaceprint(text.lower()) # " hello, world! welcome to python. "print(text.upper()) # " HELLO, WORLD! WELCOME TO PYTHON. "print(text.replace("World", "Data Science"))
print(text.split()) # Split by whitespace β list of wordsprint(", ".join(["a", "b", "c"])) # "a, b, c"# ============ REGULAR EXPRESSIONS ============text = "Contact us at [email protected] or call 555-123-4567"# Find all email addressesemails = re.findall(r'[\w.]+@[\w.]+', text)
print(emails) # ['[email protected]']# Find all phone numbersphones = re.findall(r'\d{3}-\d{3}-\d{4}', text)
print(phones) # ['555-123-4567']# Search for a patternmatch = re.search(r'\d+', "Order #12345")
print(match.group()) # "12345"# ============ WORD FREQUENCY ============from collections import Counter
text = "the cat sat on the mat the cat likes the mat"words = text.lower().split()
freq = Counter(words)
print(freq.most_common(3))
# [('the', 4), ('cat', 2), ('mat', 2)]# Remove stop wordsstop_words = {"the", "on", "a", "an", "is", "in"}
filtered = [wforwinwordsifwnotinstop_words]
print(Counter(filtered).most_common(3))
# [('cat', 2), ('mat', 2), ('sat', 1)]
Common Regex Patterns
Pattern
Matches
Example
\d
Any digit (0-9)
\d{3} matches "123"
\w
Word character (a-z, A-Z, 0-9, _)
\w+ matches "hello_world"
\s
Whitespace (space, tab, newline)
\s+ matches any spaces
.
Any character except newline
a.c matches "abc", "a1c"
+
1 or more of previous
\d+ matches "123"
*
0 or more of previous
ab*c matches "ac", "abc"
^
Start of string
^Hello matches "Hello world"
$
End of string
world$ matches "Hello world"
[abc]
Any of a, b, or c
[aeiou] matches vowels
Test Your Understanding
Q: What does re.findall(r'\d+', "I have 3 cats and 12 fish") return?
β οΈ Common Mistakes & Misconceptions
Week 1: Python Basics
1. "Python is not case-sensitive"
Writing Print("hello") instead of print("hello"), or using True as true. Python IS case-sensitive β every character matters.
β Always use lowercase for built-in functions: print(), len(), type(). Boolean values are capitalized: True, False, None.
2. Concatenating strings and numbers directly
"I am " + 25 + " years old" β TypeError: can only concatenate str to str (FAQ #14)
β Convert with str(): "I am " + str(25) or use f-strings: f"I am {25} years old". F-strings handle conversion automatically.
3. Confusing = and ==
Using x = 5 when you mean to check equality x == 5. One assigns, the other compares.
β = is assignment (x = 5 stores 5 in x). == is comparison (x == 5 returns True/False). Use == in if statements.
4. Modifying a list while iterating over it
Removing items from a list inside a for loop causes skipped elements or IndexError.
β Create a new list with list comprehension: filtered = [x for x in items if x != "remove"]. Never modify a collection while looping through it.
5. Forgetting that range() excludes the stop value
range(1, 5) produces [1, 2, 3, 4], NOT [1, 2, 3, 4, 5]. Beginners expect 5 to be included.
β range(start, stop) goes from start to stop-1. To include 5: range(1, 6). Think of it as "up to but not including."
Week 2: Data Manipulation
6. Using df["col"] = df["col"].fillna(value) without inplace
Writing df["Age"].fillna(0) but forgetting to assign it back. fillna() returns a new Series by default.
β Either df["Age"] = df["Age"].fillna(0) or df["Age"].fillna(0, inplace=True). Always assign the result!
β loc = label-based (inclusive both ends). iloc = integer position-based (exclusive stop, like range()). When in doubt, use iloc for predictable slicing.
Week 3: EDA & Visualization
8. "Correlation means causation"
Seeing a high correlation between two variables and concluding one causes the other.
β Correlation only measures how variables move together. Always look for confounding variables. Ice cream sales and drownings correlate because both increase in summer β not because one causes the other.
9. Using mean for skewed data
Reporting mean salary as $80K when most employees earn $50K and a few executives earn $500K.
β For skewed distributions, use median (robust to outliers). Always visualize first β a histogram reveals whether mean or median is more representative.
10. Forgetting the raw string prefix in regex
re.findall("\bword\b", text) fails because \b is a backspace character in normal strings.
β Always use raw strings with regex: r"\bword\b". The r prefix tells Python to treat backslashes literally.