Python for Data Analysis
Topic 7 of 14 · In Data Analysis · September 8, 2026
From zero to pandas: the Python you actually need as an analyst — notebooks, fundamentals, the DataFrame, and cleaning + aggregating data with code.
Overview
Python is the language where your analysis stops being limited by spreadsheet rows or one window — where you can clean 200,000 rows, rerun an analysis instantly with new data, and hand a colleague a script that reproduces your whole pipeline. Even though you will reach for Excel and Power BI for many tasks, Python is what job postings mean by "programming", and it is the bridge into EDA and machine learning next.
This topic teaches the analyst's Python — not a computer-science course. You will learn just enough language fundamentals to read and write script-like code, then spend most of your time in pandas, the library that makes Python behave like a supercharged spreadsheet with a memory.
Before You Start
- Complete the Data Cleaning topic so you can re-express its workflow in code, and know what a transformation log is before you write your clean functions.
- Install Python 3.8 or later with pandas, numpy and jupyter, and start a Jupyter notebook before the lesson.
- Reuse the messy CSV from the cleaning topic — you will clean it again, this time with pandas.
- Practise running a cell with Shift+Enter and adopt the habit of Kernel, Restart and Run All before trusting any numbers.
- Refresh the SQL grain thinking: one row in orders means one order line, and merges can duplicate rows when keys are not unique.
Learning Objectives
- Run Python in a Jupyter notebook and understand the cell-based workflow
- Use core syntax: variables, types, collections, loops, conditionals, functions, f-strings
- Understand Python's zero-based indexing, slicing and methods
- Use NumPy arrays for fast numeric operations and understand the "run on all rows" idea
- Load data into a pandas DataFrame and inspect it (head, info, describe, shape, dtypes)
- Select and filter rows and columns with loc/iloc, boolean masks and query
- Clean in pandas: dropna/fillna, drop_duplicates, replace, strip, string methods, astype, to_datetime
- Aggregate with groupby + agg, and reshape with pivot_table
- Combine tables with merge and join, mirroring SQL JOINs
- Export clean results and structure a reproducible notebook (markdown, functions, clear output)
Prerequisites
Basics through SQL give the concepts; Data Cleaning gives the workflow you will re-express here. No programming background needed — this starts from zero and moves at analyst speed.
Why Python, and Where It Fits in Your Path
Excel and Power BI are fantastic — until the data is huge, the task is repetitive, or you need the exact same analysis every week with zero clicking. Python's analyst strengths:
- Scale and speed — read and transform millions of rows in seconds
- Automation — one script does Monday's, Tuesday's and next month's job
- Reproducibility — the script is your documented methodology
- Ecosystem — pandas, plus plotting (matplotlib, seaborn) and, later, statistics/scikit-learn
In this path, Python supersizes your data-cleaning and prep work and becomes the workhorse for Exploratory Data Analysis. You will still use Power BI for dashboards and Excel for quick checks — professionals use all three.
Getting Started: Install and Notebooks
You need three pieces: Python (the 3.x runtime), a code environment, and pandas (plus NumPy). The analyst-standard environment is Jupyter notebooks — a document of cells mixing markdown notes and runnable Python, ideal for analysis that tells a story top to bottom.
# terminal: python --version # verify Python 3.8+ pip install pandas numpy jupyter # install your analysis stack # then: jupyter notebook # opens the notebook UI in your browser
In a notebook: run a cell with Shift+Enter; an In [5] counter appears. The golden cell habit: one idea per cell, run top to bottom, and re-run everything after any change — a cell run out of order is the #1 source of "but it worked a minute ago".
Python Fundamentals for Analysts
Don't learn a programming language — learn a toolbox. These few pieces carry 95% of analyst code:
# Variables & types
name = "Cairo" # str
price = 49.99 # float
orders = 1200 # int
in_stock = True # bool
# Collections
cities = ["Cairo", "Alex", "Giza"] # list (ordered)
info = {"region": "North", "target": 100000} # dict (key → value)
# Loop + conditional
for city in cities:
if city.startswith("C"):
print(f"Starts with C: {city}") # f-string
# Function
def margin(revenue, cost):
return (revenue - cost) / revenue- Zero-indexing:
cities[0]is the first element; slicingcities[1:3]takes positions 1–2 - Methods — actions on values:
" Hi ".strip(),cities.append("Mansoura"),name.lower() - Indentation is syntax — four spaces under
if/for/def; inconsistent indentation is the beginner bug
You will not write a lot of loops in pandas (the library vectorizes them for you) — but you must be able to read them and debug them.
sales = {'monday': 1200, 'tuesday': 980, 'wednesday': 1430}
total = 0
for amount in sales.values():
total += amount
print(f'Total week = {total:,}')NumPy: Fast Tables of Numbers
NumPy gives you arrays — grids of numbers where every operation applies to the whole grid at once (vectorized). You rarely call NumPy directly, but it powers pandas, and understanding the "operate on everything" idea unlocks everything else.
import numpy as np amounts = np.array([100, 250, 400, 700]) # a numeric vector discounted = amounts * 0.9 # applies to every element! print(discounted) # [ 90. 225. 360. 630.] print(amounts.mean()) # 362.5 print(amounts[amounts >= 300]) # boolean filter: array([400, 700])
Notice there is no loop: the operation runs on all rows because the array knows itself as one object. That same speed and simplicity is exactly how pandas handles whole columns.
pandas: The Analyst's Power Tool
pandas gives you two objects: a Series (one labeled column) and a DataFrame (labeled rows × columns — think "a spreadsheet in code").
import pandas as pd
df = pd.read_csv("orders.csv") # load CSV
df.head() # first 5 rows
df.shape # (rows, columns)
df.columns # column names
df.info() # types + nulls — your profile in one call
df.describe() # count/mean/min/max/percentiles for numeric columns
df["region"].value_counts() # categorical profileWith df.head(), df.info() and df.describe() you have just replaced your Excel/SQL profiling step — in three lines, on any size file. That is the moment the power of code becomes obvious.
df = pd.read_csv('your_file.csv')
# Your first exploration:
print(df.shape)
print(df.isna().sum()) # nulls per column
print(df.nunique()) # distinct values per columnSelecting, Filtering and Deriving
Two selection styles cover everything:
# By label: df.loc[row_selector, column_selector]
# By position: df.iloc[row_position, column_position]
df.loc[:, ["order_id", "amount"]] # pick columns by name
df.loc[df["region"] == "North"] # rows where region is North
# Boolean mask → the SQL WHERE
df.loc[(df["amount"] >= 500) & (df["status"] == "shipped")]
# Or the query() sugar
df.query("amount >= 500 and status == 'shipped'")
# New derived column (vectorized, like a calculated column)
df["revenue"] = df["quantity"] * df["price"]
df["order_size"] = df["revenue"].apply(lambda v: "Large" if v >= 500 else "Small")&(and) and|(or) — never Python'sand/oron arrays; parentheses around each condition are required.apply()runs row-wise logic when a vectorized expression is not easy
This mirrors Excel's filter + XLOOKUP + IF, all evaluated for the entire table at once.
Cleaning in pandas
Every trick from your data-cleaning topic now has a one-liner:
# Missing values
clean = df.dropna(subset=["order_id"]) # drop rows missing a key column
clean = df.fillna({"region": "UNK"}) # fill a column with a default
# Duplicates — define the key first
clean = clean.drop_duplicates(subset=["order_id"], keep="last")
# Text standardization
clean["region"] = clean["region"].str.strip().str.title()
# Types
clean["order_date"] = pd.to_datetime(clean["order_date"]) # true dates
clean["price"] = clean["price"].astype(float)
# Replace / recode categories
clean["segment"] = clean["segment"].replace({"prem": "premium", "stnd": "standard"})Notice the method chain pattern: read → drop → fill → dedupe → standardize → type, all as script steps. This is your Raw → Clean pipeline as executable, reviewable code — run it on a new file tomorrow and it recreates the exact same result.
print(clean.isna().sum()) # confirm nulls after cleaning
print(clean.duplicated(subset=['order_id']).sum()) # remaining duplicatesGrouping and Combining Tables
Your SQL muscle memory transfers directly:
# GROUP BY in pandas
df.groupby("region")["amount"].sum() # revenue by region
df.groupby(["region", "month"]).agg(
orders = ("amount", "count"),
revenue = ("amount", "sum"),
avg = ("amount", "mean"),
).reset_index()
# SQL-style JOINs
merged = orders.merge(customers, on="customer_id", how="left") # LEFT JOIN
# Pivot — like a PivotTable
df.pivot_table(index="region", columns="month",
values="amount", aggfunc="sum")After every merge, check the shape: merged.shape — a many-to-many join can silently duplicate rows (the same trap as SQL).
Export, Structure, Reproducibility
Finish like a professional:
clean.to_csv("orders_clean.csv", index=False) # export, no row numbers
# save a single frame for quick inspection
summary = df.groupby("region")["amount"].sum().reset_index()
summary.to_excel("region_report.xlsx", index=False)And follow notebook hygiene that colleagues (and future-you) will thank you for: explain each section with a markdown cell (title, source, question); keep one table → one analysis step; name DataFrames meaningfully; don't print the whole table; and when an analysis grows beyond a page, split reusable logic into functions.
The unspoken rule: your notebook is your methodology document. A reviewer should be able to re-run it end-to-end and get the same numbers — that is reproducibility, and it is the difference between "I found this" and "here is the evidence".
Hands-On Practice
Reuse the messy CSV from your data-cleaning topic — this time by code.
- Load it with pandas and profile it in three lines (shape, isna-sum, nunique).
- Clean it in a method chain: drop dupes on the key, fill nulls (sensible defaults), standardize text, convert dates and numbers.
- Verify the cleaning (isna().sum() and duplicated().sum() = 0 on the key).
- Answer 4 business questions with groupby/agg and merge (e.g. revenue by region × month, top category, salesperson rank).
- Export the clean table and one summary and confirm both re-run from a fresh kernel.
Set up Jupyter; do 10 small drills in a scratch notebook: variables, lists, dicts, loops, functions, f-strings. If it solves quickly, keep going — the goal is comfort reading and running, not memorizing.
Deeper Worked Examples
Profile and clean a messy export in one method chain
Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Group, merge and answer three business questions
Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Common Mistakes
- Running cells out of order, then trusting stale results — restart & run all
- Setting df = df.copy() everywhere out of fear, or never copying and mutating your input
- Using Python 'and'/'or' on arrays instead of & and | (with parentheses)
- Merging two tables and not checking the row count explodes
- Forgetting pandas is zero-indexed and columns are labels, not positions
- Doing .apply(lambda) row-wise when a vectorized string/date method exists
- Reading but never writing a reproducible notebook + exported artifacts
- Ignoring dtypes: a column of '9' strings quietly wrecks every sum
Real-World Usage
Python appears in analytics interviews both as takehome code and as screening questions: "load this, clean it, answer these three questions, email the script". What they grade is exactly what this topic trained: correct pandas idioms, a clean reproducible notebook, thoughtful cleaning decisions, and clearly communicated results. On the job, Python is your automation arm — scheduled ETL scripts, exploratory studies, ad-hoc analyses too big for Excel — and it is the prerequisite for the EDA topic next: filling notebooks with numbers, charts and honest conclusions before anything gets presented to a stakeholder.
Mini Project
Business problem: The growth team keeps getting different answers from different people for the same question. They ask you to produce one canonical weekly analysis, fully reproducible.
Dataset: any public retail CSV (or your cleaned data-cleaning export), 1,000+ rows, with date, region, category, salesperson and amount.
Objective: one clean, automated, reproducible pipeline + a concise weekly summary notebook.
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
| Deliverable | Proves |
|---|---|
| Clean reproducible pipeline | polish: functions + Restart & Run All |
| Profile in code | Survey-before-touch in pandas |
| Weekly KPI summary | groupby/agg + merge mastery |
| Exported artifacts | Deliverable files, not just demo code |
| Documented notebook | Colleague-reviewable methodology |
Key Takeaways
- Python power = scale, automation, reproducibility and the data ecosystem
- Jupyter cells mix notes and code; restart & run all when results are odd
- Fundamentals: variables, lists, dicts, loops, functions, f-strings, zero-indexing
- NumPy vectorizes math — operate on the whole array, never per-cell
- pandas DataFrame = labeled spreadsheet in code; head/info/describe profile anything
- loc/iloc, boolean masks (…&… or …|…) and query() cover all filtering
- Cleaning is a method chain; verify with isna().sum() and duplicated().sum()
- groupby/agg, pivot_table and merge = the SQL you already know
- A well-structured notebook is your methodology document
Key Terms & Glossary
| Term | Meaning |
|---|---|
| DataFrame | pandas' two-dimensional labelled table — a spreadsheet in code, with named columns and an index. |
| Series | A single labelled column inside a DataFrame, which is also what you get when you select one column. |
| vectorisation | Applying an operation to a whole column at once, like df['price'] times 0.9, in fast compiled code instead of looping per row. |
| boolean mask | A Series of True and False used to filter rows — the pandas equivalent of SQL's WHERE, built with the ampersand and pipe operators and parentheses. |
| method chaining | Writing cleaning steps one after another, each operating on the previous result, so the Raw-to-Clean pipeline reads top to bottom. |
| groupby | The pandas operation that splits rows into groups and applies an aggregation such as sum, count or mean to each — SQL's GROUP BY. |
Learning Resources
Python.org — The Python Tutorial
The official, free introduction to the language — work through part 1 for fundamentals.
Python for Everybody (py4e)
Free book and video course that takes you from zero to working code.
pandas — Getting Started
Official 10-minute- to-tutorial intro to DataFrames, selection, grouping and joining.
Kaggle — pandas Course
Short interactive lessons that pair perfectly with this module's practice.
Real Python
Extensive tutorials, from Python fundamentals to pandas, notebooks and automation.
Automate the Boring Stuff with Python
The celebrated free book for practical scripts — great follow-up after this module.
Chapter Quiz
Chapter Quiz — Python for Data Analysis
Notebooks, fundamentals, NumPy, the pandas DataFrame, cleaning, grouping and reproducibility.
Question 1 of 5
A Jupyter notebook produces different numbers than an hour ago. What is the fastest first fix?
Knowledge Check
End-of-Topic Exam
Hint: Parentheses around each condition in the mask; the word operators inside query.
Model answer: The boolean mask form is df.loc[(df['amount'].ge(500)) & (df['status'].eq('shipped'))], where ge and eq replace the comparison symbols and the ampersand combines conditions. The query form is df.query('amount ge 500 and status equals shipped') written in pandas' word operators, remembering that the mask uses the ampersand while query uses the word 'and'.
Hint: Row multiplication on an ununique key.
Model answer: The join key is not unique on one side, so the rows multiplied out — a many-to-many join. Check each side before merging with print(orders['customer_id'].duplicated().sum()) and print(customers['customer_id'].is_unique), then clean or aggregate the duplicates down to the intended grain and merge again.
Hint: Groupby with .agg and named tuples; verify the row count.
Model answer: The call is result = orders.groupby(['region', 'month']).agg(orders=('amount', 'count'), revenue=('amount', 'sum')).reset_index(), which names the columns orders and revenue. After merging anything, check merged.shape or merged.duplicated().sum() so a multiplication of rows never reaches your summaries silently.
Hint: Cell order first, then inputs, then mutations.
Model answer: One: cells were run out of order after an edit — fix with Kernel, Restart and Run All. Two: an input changed, such as a stale file, a changed dtype or an overwritten dataset — re-read the source and confirm the dtypes. Three: a shared DataFrame was mutated mid-analysis instead of copied — find in-place assignments and copy before transforming.