AI in Medicine — Summer Course 2026

Python for
Data Science

A hands-on workshop for biomedical professionals —
from theory to real data analysis in ~2.5 hours

27 July 2026 1400–1715 Google Colab
🧑‍💻
Your Instructor

Koay Hong Vin

Education
B.Eng. Electrical Engineering
PhD in Artificial Intelligence — Autonomous Vehicles
Current
Risk Modelling and Data Scientist
Ant International
01 / Agenda

What We'll Cover Today

01
Foundations & Python Refresher
~25 min
02
NumPy Essentials
~20 min
03
Pandas Fundamentals
~35 min
04
Data Visualization
~20 min
05
Mini Project: Malaysia Births
~40 min
06
Wrap-up & Next Steps
~10 min
02 / Context

Why Python for Biomedical Data?

  • Free & Open Source — no license fees, unlike SAS or SPSS. Anyone can use it, anywhere.
  • Reproducible Research — scripted analysis that anyone can re-run. No more "which Excel cell did I click?"
  • Handles Real Data — Excel chokes on 1M rows. Pandas handles 100M+ rows and files like CSV, Excel, Parquet, SQL.
  • Rich Ecosystem — stats (SciPy), ML (scikit-learn), bioinformatics (Biopython), imaging (scikit-image). All in one language.
  • Industry Standard — used in NIH, Oxford, Nature-published research, and every major pharma company.
03 / Discipline

What is Data Science?

  • The field — turning raw data into decisions by combining statistics, programming, and domain knowledge.
  • Three pillars — maths & stats, computer programming, and biomedical expertise. The most valuable insights sit where they overlap.
  • It’s a cycle, not a step — ask a question, get data, clean it, explore, analyse, communicate, then ask a sharper question.
  • Why now in medicine? — EHRs, wearables, omics, imaging. The bottleneck is no longer data; it’s people who can interpret it.
~80%
of a data scientist’s time is spent cleaning & preparing data — not modelling.
3 + 1
pillars: stats, code, domain — plus communication to make it count.
04 / Workflow

The Data Analysis Workflow

01 · Ask
Define a sharp question: “Are live births lower on weekends?”
📥
02 · Get
Load the data. CSV, Excel, SQL, or an API. We’ll use read_csv().
🧹
03 · Clean
Missing values, wrong types, duplicates, outliers. Often 80% of the work.
🔍
04 · Explore
Summarise & plot. Look before you leap — patterns appear in pictures.
📈
05 · Analyse
Correlation, t-tests, models. Put numbers on what the eye sees.
📣
06 · Share
Charts + a reproducible notebook. Insight that isn’t read is wasted.
“Today we walk through all six steps — once you see the loop, every dataset is just another lap.”
05 / Python

Python Refresher

  • Variables & typesx = 5 (int), weight = 70.2 (float), name = "Ali" (str), diabetic = True (bool). Python infers the type.
  • Lists — ordered & mutable: [5.2, 4.8, 6.1]. Indexing starts at 0, so values[0] is the first element.
  • Dictionaries — key → value pairs: {"age": 45, "bp": 130}. Look up by name, not position — much like a patient record.
  • Functions — reusable blocks: def square(x): return x*x. Or lean on built-ins like len() and print().
  • Imports — borrow power: import numpy as np. The community’s libraries do the heavy lifting for you.
# A patient record as a dict
patient = {"name": "Ali", "age": 45}

# A function we'll reuse
def bmi(weight_kg, height_m):
    return weight_kg / (height_m ** 2)

print(bmi(70, 1.75))   # 22.86
06 / Data Types

Types of Data

🔢
Numerical — Continuous
Measured on a smooth scale — any value within a range is possible, in theory down to infinite decimals.

Everyday — your height (1.753 m), the temperature (27.4°C), the time it takes to drive to work (23.7 min).

Biomedical — blood pressure 122.3 mmHg, BMI 22.86, serum glucose 5.4 mmol/L, tumour diameter 3.2 cm.

Valid ops — mean, difference, ratio (“twice as much”), regression on the raw number.
🧮
Numerical — Discrete
Counted in whole numbers — you can’t have 2.3 of them. Arises from counting events, not measuring.

Everyday — number of children in a family (3), cars in the carpark (47), goals in a match (2).

Biomedical — pregnancies (gravida 4), admissions per day (12), lesions on a CT (3), metastatic lymph nodes (2 of 15).

Valid ops — mean is meaningful but the value itself is a count; ratios (“2× the polyps”) need care.
🏷️
Categorical — Nominal
Named groups with no inherent order. The numbers we assign (e.g. A=1, B=2) are just labels — they don’t add or rank.

Everyday — blood type, brand of phone, favourite colour, postcode, marital status.

Biomedical — ABO blood group, sex, ICD-10 code, hospital site, eye colour. The simplest case is binary: alive/dead, smoker/non-smoker, pregnant/not.

Valid ops — count per category, proportions, chi-square. Never average the codes.
📊
Categorical — Ordinal
Named groups with a meaningful order — but the gaps between steps aren’t equal. Stage II → III isn’t the same jump as III → IV.

Everyday — S/M/L t-shirt sizes, education level (primary/secondary/degree), movie ratings (1–5 stars), Hot–Medium–Mild spice.

Biomedical — cancer stage I–IV, NYHA heart-failure class I–IV, Likert pain 0–10, Gleason score 6–10, ASA physical-status class I–V.

Valid ops — median, order statistics, rank-based tests. Means are common but technically a stretch.
The data type dictates the analysis you can do and the plots that make sense — means are nonsense on nominal codes; bar charts are wrong for continuous values. Picking the wrong tool is the most common beginner mistake.
07 / Summaries

Descriptive Statistics

  • Centre — mean, median, mode. The mean is sensitive to outliers; the median is robust. Use median for skewed data like income or length-of-stay.
  • Spread — range, std, variance, IQR. Two groups can share the same mean but differ wildly in spread.
  • Position — percentiles & quartiles. The 95th percentile of blood pressure is clinically more useful than the mean.
  • Always visualise too — summary numbers hide shape. Anscombe’s quartet: four datasets with identical stats, totally different plots.
import numpy as np

# 20 systolic BP readings (mmHg)
bp = np.array([118, 125, 142, 160, 134,
                    122, 150, 128, 137, 145,
                    119, 130, 141, 156, 121,
                    133, 138, 127, 144, 135])

print(f"mean = {bp.mean():.2f}")  # 135.25
print(f"median = {np.median(bp):.2f}"# 134.50
print(f"std = {bp.std():.2f}")  # 11.67
print(f"IQR = {np.percentile(bp, [25,75])}")
08 / Inference

Distributions & Significance

  • Distribution — the shape of your data. The normal (bell) curve fits many biological traits (height, BP), but CRP and length-of-stay are skewed.
  • Null hypothesis (H₀) — the default claim: “no difference”. A p-value is the probability of seeing your result if H₀ were true.
  • p < 0.05 — a convention, not a law. With 38,000 rows, even trivial differences become “significant”. Always pair it with an effect size.
  • Correlation ≠ causation — ice-cream sales and drownings both rise in summer; heat drives both. Design — not maths — establishes causation.
  • Clinical vs statistical — significance asks “did it exist?”; clinical significance asks “does it matter to the patient?”
import numpy as np
from scipy import stats

# ── 1 · SHAPE — is the data symmetric? (bullet 1)
weekday = np.array([1800,1820,1770,1850,1790,
  1880,1810,1840,1760,1890])
print(f"skew = {stats.skew(weekday):.2f}")  # 0.23 → near-symmetric

# ── 2 · H₀ test — “no difference” (bullets 2 & 3)
weekend = np.array([1620,1580,1650,1540,1610,
  1570,1690,1600,1640,1580])
t, p = stats.ttest_ind(weekday, weekend)
print(f"t = {t:.2f} p = {p:.2e}")     # 10.86 2.5e-09 ⇒ reject H₀
# but how big is the effect? (bullet 5)
print(f"diff = {weekday.mean()-weekend.mean():.0f} births/day")  # 213

# ── 3 · Correlation ≠ causation (bullet 4)
temp = np.array([27,28,29,29,29,28,28,28,27])
births = np.array([1750,1780,1820,1830,1810,1790,1770,1760,1750])
r, p2 = stats.pearsonr(temp, births)
print(f"r = {r:.3f} p = {p2:.4f}")  # r=0.934 — strong link, but heat ≠ cause
09 / NumPy

NumPy — The Foundation

  • Arrays — fast, vectorized containers for numerical data. Think Excel column, but in memory.
  • No Loops Needed — operations apply to entire arrays at once. 10,000 patient readings? One line.
  • Built-in Stats — mean, median, std, percentiles. Critical for lab values, vitals, clinical measurements.
import numpy as np

# 20 fasting glucose readings (mmol/L)
glucose = np.array([5.2, 4.8, 6.1, 5.5, 5.9,
                         4.7, 6.3, 5.0, 5.8, 5.3,
                         5.6, 4.9, 6.0, 5.4, 5.7])

print(f"mean = {glucose.mean():.2f}")  # 5.48
print(f"std = {glucose.std():.2f}")   # 0.48
print(f"P95 = {np.percentile(glucose, 95):.2f}"# 6.16
10 / Pandas

Pandas — DataFrames

  • DataFrame — 2D table with named columns. The central object in data analysis.
  • Read Anything — CSV, Excel, Parquet, SQL, JSON. Load from file or URL.
  • Filter & Group — SQL-like operations: filter rows, group by categories, aggregate.
  • Handle Dates — datetime parsing, extract year/month/day, time-series analysis.
import pandas as pd

# Load directly from web
df = pd.read_csv('https://raw.githubusercontent.com/datasets/population/master/data/population.csv')

df.head()       # first rows
df.describe()   # summary stats
df.groupby('Year')['Value'].sum()
11 / Visualization

Matplotlib & Seaborn

📈
Line Plots
Trends over time. Births per year, disease incidence, lab values over treatment course.
📊
Bar Charts
Compare categories. Births by month, drug efficacy by group, demographics.
📦
Box Plots
Show distributions. Compare decades, treatment arms, identify outliers.
📉
Histograms
Frequency distributions. Daily birth counts, patient ages, biomarker levels.
import matplotlib.pyplot as plt

months = ['Jan','Feb','Mar','Apr','May','Jun']
births = [1750, 1680, 1820, 1790, 1850, 1830]

plt.figure(figsize=(8,4))
plt.plot(months, births, marker='o', color='#0d9488')
plt.title('Avg Daily Births by Month')
plt.ylabel('Births')
plt.show()
12 / Dataset

Our Data: Malaysia Daily Live Births

  • Source — National Registration Department (JPN), via data.gov.my
  • Time Range — 1920 to 2023 (~38,000 rows)
  • Columns — date, state, births (3 columns, clean data)
  • Why Biomedical? — Birth demography underpins public health planning, maternal health policy, hospital staffing.
  • License — CC BY 4.0 (free to use, share, adapt)
👶
13 / Setup

How We'll Work

🌐
Google Colab
No installation needed. Python, NumPy, Pandas, Matplotlib, and Seaborn all pre-installed. Runs in your browser.
⌨️
Code-Along
I'll type, you follow. Every line of code runs and produces output immediately. You'll leave with a working notebook.
✏️
Exercises
Short exercises after each section. Try it yourself, then we'll review together. No grades — just learning.
💬
Ask Anytime
Questions encouraged throughout. If something doesn't make sense, it probably doesn't make sense to others too.
14 / Recap

The Big Picture

NumPy
Fast arrays & numerical computing
Pandas
Data manipulation & analysis
Plots
Matplotlib & Seaborn for visualization
"Together, these three form the complete data analysis pipeline — from raw numbers to publication-ready figures."
🚀

Let's Begin!

Open your notebook. Let's write some Python.

Home 1 / 17 Download Notebook