Python for Actuarial Students · Course 0W
Module 8 · Part B

A Taste of Python

print, arithmetic, NumPy, pandas, and charts — then publish your notebook and commit the finished project.

Module 8B · OverviewBy the end of this deck you can…

  • Format output with print() and f-strings
  • Use Python as a financial calculator
  • Use NumPy for vectors, matrices, and solving linear systems
  • Load and summarize a dataset with pandas
  • Draw charts with matplotlib and seaborn
  • Export notebooks to HTML and PDF — from the CLI and from VS Code
  • Build, document, and commit a complete project
45 min
Guided tour (type along!)
45 min
Final lab

This is a taste, not a lesson plan for each topic — the following courses go deep on each.

Companion notebook: module-08b-taste-of-python.ipynb — worked examples and self-checking exercises.

SetupAdd the packages we need

uv add numpy pandas matplotlib seaborn
uv add --dev jupyterlab ruff        # skip any you already added in Part A
code .

Then create notebooks\02_taste.ipynb with the .venv kernel and type along. Put a Markdown heading above each section as you go.

Typing (not pasting) the examples is the fastest way to learn. Make typos. Read the error messages. Fix them.

Part 1

Python Basics

print() and Python as a calculator.

print()Talking to the outside world

print("Hello, actuaries")          # Hello, actuaries
print("PV =", 772.17)              # PV = 772.17
print("a", "b", "c", sep=" | ")    # a | b | c

name = "Jane"
rate = 0.0372
reserve = 1234567.891

print(f"Analyst: {name}")          # Analyst: Jane
print(f"Lapse rate: {rate:.1%}")   # Lapse rate: 3.7%
print(f"Reserve: {reserve:,.2f}")  # Reserve: 1,234,567.89
print(f"{'Age':<5}{'qx':>8}")      # Age        qx

f-strings (f"…") insert values into text. After a colon, a format spec controls the look:

:.2f2 decimal places
:,.2fthousands separator too
:.1%as a percentage
:<5 / :>8left / right align in a width

CalculatorPython as a (very good) financial calculator

OperatorExampleResult
+ - *3 * (2 + 4)18
/7 / 23.5
// floor division7 // 23
% remainder7 % 21
** power1.05 ** 21.1025

^ is not “power” in Python (it’s bitwise XOR). Excel users: use **.

i = 0.05          # effective annual rate
n = 10            # term in years
v = 1 / (1 + i)   # discount factor

# Accumulate 1,000 for 10 years
round(1000 * (1 + i) ** n, 2)        # 1628.89

# Present value of 1,000 due in 10 years
round(1000 * v ** n, 2)              # 613.91

# Annuity-immediate: a-angle-n at 5%
a_n = (1 - v ** n) / i
round(a_n, 4)                        # 7.7217
Part 2

NumPy

A vector and matrix calculator.

NumPyVectors: whole columns at once

import numpy as np

t  = np.arange(1, 11)       # [ 1  2  3 ...  10]
v  = 1.05 ** -t             # 10 discount factors at once
cf = np.full(10, 100.0)     # 100 paid at the end of each year

pv = (cf * v).sum()         # element-wise multiply, then add up
print(round(pv, 2))         # 772.17
round(pv, 2)                # np.float64(772.17): same value, NumPy type

cf @ v                      # same thing as a dot product
  • A NumPy array is like an Excel column you can do math on in one go — no dragging formulas down
  • Operations apply element-wise: 1.05 ** -t computes all ten powers
  • @ is matrix / dot-product multiplication

Same answer as 100 * a_n from the previous slide — but this version handles any cash-flow pattern.

NumPySolving a system of linear equations

Three bonds, their cash flows at t = 1, 2, 3, and market prices. Which discount factors d1, d2, d3 price them all?

$$\begin{pmatrix}105&0&0\\6&106&0\\4&4&104\end{pmatrix}\begin{pmatrix}d_1\\d_2\\d_3\end{pmatrix}=\begin{pmatrix}100.00\\101.00\\96.50\end{pmatrix}$$

Each row: price = Σ cash flow × discount factor. That’s C d = P.

C = np.array([[105,   0,   0],     # 1-yr bond, 5% coupon
              [  6, 106,   0],     # 2-yr bond, 6% coupon
              [  4,   4, 104]])    # 3-yr bond, 4% coupon
P = np.array([100.00, 101.00, 96.50])

d = np.linalg.solve(C, P)
d.round(4)          # array([0.9524, 0.8989, 0.8567])

# Implied spot rates, in %
t = np.arange(1, 4)
spot = d ** (-1 / t) - 1
(spot * 100).round(2)   # array([5.  , 5.47, 5.29])

np.linalg.solve handles 3 equations or 3,000 — the same one line. (You just bootstrapped a yield curve.)

Part 3

pandas

Spreadsheets, programmable.

pandasThe sample dataset

Save this as data\policies.csv (VS Code: New File, paste, save):

policy_id,issue_age,sex,product,sum_assured,annual_premium,status
P001,34,F,TERM,250000,310.50,IN_FORCE
P002,45,M,TERM,500000,980.00,LAPSED
P003,29,F,WHOLE_LIFE,100000,1450.00,IN_FORCE
P004,52,M,WHOLE_LIFE,200000,3890.00,IN_FORCE
P005,41,F,TERM,300000,455.25,LAPSED
P006,38,M,TERM,400000,620.00,IN_FORCE
P007,60,F,WHOLE_LIFE,150000,4210.00,DEATH_CLAIM
P008,33,M,TERM,350000,402.75,IN_FORCE

This file is small and synthetic, so it lives in data\ and gets committed. Real extracts go in data\raw\, which .gitignore keeps out of Git (Module 5).

pandasLoad and look

import pandas as pd

df = pd.read_csv("../data/policies.csv")

df.head()        # first 5 rows, as a table
df.shape         # (8, 7) → rows, columns
df.dtypes        # the type of each column
df.describe()    # count, mean, std, min, max…
[3]:
df.head(3)
[3]:
policy_idissue_ageproductannual_premiumstatus
0P00134TERM310.50IN_FORCE
1P00245TERM980.00LAPSED
2P00329WHOLE_LIFE1450.00IN_FORCE

(some columns omitted to fit the slide)

Excel files work too: pd.read_excel("../data/raw/extract.xlsx", sheet_name="Policies") — that’s what openpyxl is for.

pandasAsk questions of the data

# One column
df["annual_premium"].mean()             # np.float64(1539.8125)

# Filter rows
df[df["issue_age"] >= 50]               # P004, P007

# A new calculated column
df["rate_per_mille"] = (
    df["annual_premium"] / df["sum_assured"] * 1000
)

# Count by category
df["status"].value_counts()

# Summarize by group (a pivot table)
df.groupby("product")["annual_premium"].mean().round(2)
status
IN_FORCE       5
LAPSED         2
DEATH_CLAIM    1
Name: count, dtype: int64

product
TERM           553.70
WHOLE_LIFE    3183.33
Name: annual_premium, dtype: float64

groupby is a pivot table you can re-run on next quarter’s extract without touching a single cell.

Part 4

Charts

matplotlib for control, seaborn for statistical graphics.

matplotlibThe foundation

import matplotlib.pyplot as plt

avg = df.groupby("product")["annual_premium"].mean()

fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(avg.index, avg.values, color=["#0e6b6b", "#c26a1b"])
ax.set_title("Average annual premium by product")
ax.set_ylabel("Premium")

fig.savefig("../output/premium_by_product.png",
            dpi=150, bbox_inches="tight")
Average annual premium by product 0100020003000 TERMWHOLE_LIFE Premium

In a notebook the chart appears below the cell automatically. savefig writes a file to output\ for reports.

seabornStatistical charts in one line

import seaborn as sns

sns.set_theme(style="whitegrid")

sns.scatterplot(data=df, x="issue_age",
                y="annual_premium", hue="product")

# other one-liners to try:
sns.boxplot(data=df, x="product", y="annual_premium")
sns.histplot(data=df, x="issue_age", bins=5)
sns.countplot(data=df, x="status")
020004000 30405060 issue_age TERM WHOLE_LIFE

seaborn understands DataFrames: name the columns, and it handles colors, legends, and axis labels.

Part 5

Publishing Notebooks

HTML and PDF for people who don’t run Python.

nbconvertFrom the command line

# HTML (always works — jupyterlab already installed nbconvert)
uv run jupyter nbconvert --to html notebooks/02_taste.ipynb --output-dir output

# Re-run every cell first, so the export is guaranteed fresh
uv run jupyter nbconvert --to html --execute notebooks/02_taste.ipynb --output-dir output

# Hide the code — results and prose only, for managers and reviewers
uv run jupyter nbconvert --to html --no-input notebooks/02_taste.ipynb --output-dir output

# PDF via LaTeX (needs MiKTeX from Module 6)
uv run jupyter nbconvert --to pdf notebooks/02_taste.ipynb --output-dir output

# PDF via a headless browser (no LaTeX needed)
uv add --dev "nbconvert[webpdf]"
uv run jupyter nbconvert --to webpdf --allow-chromium-download notebooks/02_taste.ipynb --output-dir output

--execute + --no-input is a one-line, reproducible reporting pipeline: fresh numbers, no hidden state, no code on show.

VS CodeExporting from the Jupyter extension

  1. Open the notebook; Restart → Run All
  2. Click … (More Actions) in the notebook toolbar → Export
  3. Choose HTML or PDF
  4. Pick a location — save into output\

Under the hood this uses the same nbconvert, running in your .venv kernel. PDF export needs a LaTeX distribution (MiKTeX).

No LaTeX? Export to HTML, open it in your browser, and use Print → Save as PDF.

Final Lab · 45 minYour first complete Python project

  1. Project actuarial_intro created with uv, standard folders, packages added
  2. A script, src\premium_summary.py, that uses pandas
  3. A notebook, notebooks\02_taste.ipynb, with prose, calculations, a table, and a chart
  4. An HTML export in output\
  5. A README and a clean .gitignore
  6. Everything committed to Git in small, well-described commits

Definition of done

Anyone can run:

git clone <your repo>
cd actuarial_intro
uv sync
uv run python src/premium_summary.py

…and get the same output as you.

Lab · The scriptsrc\premium_summary.py

"""Summarize the sample policy file by product."""

from pathlib import Path

import pandas as pd

DATA = Path("data") / "policies.csv"

df = pd.read_csv(DATA)
print(f"{len(df)} policies loaded from {DATA}")
print()

summary = (
    df.groupby("product")["annual_premium"]
    .agg(["count", "mean"])
    .round(2)
)
print(summary)
PS> uv run python src/premium_summary.py
8 policies loaded from data\policies.csv

            count     mean
product
TERM            5   553.70
WHOLE_LIFE      3  3183.33

Notice pathlib printed data\policies.csv — backslash on Windows — though we wrote /-style parts. Portable code, native display (Module 1).

Save → Ruff formats it. Any squiggles? Fix them.

Lab · The notebooknotebooks\02_taste.ipynb

Build it from this deck’s examples, one section per heading:

  1. Markdown: title, your name, one-line purpose
  2. Calculator: the annuity value a_n
  3. NumPy: the bond-bootstrap system and spot rates
  4. pandas: load policies.csv, describe(), value_counts(), groupby
  5. Charts: the bar chart (saved to output\) and the seaborn scatter
  6. Markdown: three bullet-point observations

Before exporting: Restart kernel & Run All. If it fails top-to-bottom, fix it before anyone else sees it.

uv run jupyter nbconvert --to html --execute `
    notebooks/02_taste.ipynb --output-dir output
start output\02_taste.html

The backtick ` at the end of a line continues a PowerShell command onto the next line.

Lab · CommitPut it all in Git

git init                                   # skip if uv already created .git
notepad .gitignore                         # add the Module 5 sections (output/, data/raw/, .env …)
git status                                 # .venv, output\ must NOT be listed

git add .gitignore pyproject.toml uv.lock .python-version
git commit -m "Set up actuarial_intro with numpy, pandas, matplotlib, seaborn"
git add data/policies.csv src/
git commit -m "Add sample policy data and premium summary script"
git add notebooks/
git commit -m "Add taste-of-Python notebook"
git add README.md .vscode/
git commit -m "Document project and share editor settings"
git log --oneline

# Optional: create an empty private repo on GitHub, then
git remote add origin https://github.com/<you>/actuarial_intro.git
git push -u origin main

Course 0W · RecapLook what you can do now

1 · Files

Read any path; keep work outside OneDrive

2 · Terminal

Navigate and manage files in PowerShell

3 · PATH

Fix “not recognized”; install with winget

4 · uv

Reproducible Python environments

5 · Git

History, diffs, and safe undo

6 · Docs

Markdown, pandoc, notebooks

7 · VS Code

One configured, shareable workspace

8 · Python

Scripts, NumPy, pandas, charts

Your PC is now a programmer’s PC.

Python for Actuarial Students
Course 0W complete

You’re ready to program.

Next: Python fundamentals in depth — built on the workspace, tools, and habits you set up here.