Introduction to Python¶
~2 hours · Google Colab · nothing to install
For graduate students with no prior programming experience.
By the end you can:
- write and run basic Python
- use functions and libraries
- load and summarize data with pandas
- plot with matplotlib
You need: a Google account and a browser. Open this notebook, then File → Save a copy in Drive.
Why Python
- free and used in every discipline
- readable syntax
- one ecosystem: data, plots, machine learning, automation
- notebooks are easy to share and rerun
1. Getting Python¶
- Google Colab — nothing to install; what we use today
- Local install — for offline work later
Option 1 · Google Colab¶
Runs in the browser, saves to Drive, ships with NumPy, pandas, and matplotlib.
- colab.research.google.com → sign in
- File → New notebook
- Type
print("Hello, world!")and press Shift+Enter
Working in Colab¶
- Shift+Enter — run a cell
- Runtime → Run all — rerun from the top
- File → Save a copy in Drive — keep your own editable copy
Option 2 · Local install (optional)¶
Anaconda — recommended for research anaconda.com/download → install → Navigator → Jupyter Notebook → New → Python 3
Python.org — minimal python.org/downloads → install. On Windows, check Add Python to PATH.
The notebook interface¶
Cells — code cells run Python; markdown cells hold notes.
Shortcuts — Shift+Enter run and move · Cmd/Ctrl+Enter run and stay · A insert above · B insert below
print("Hello, world!")
Variables and data types¶
A variable is a name that stores a value.
| type | holds | example |
|---|---|---|
int |
whole numbers | 3, -10 |
float |
decimals | 3.14 |
str |
text | "hello" |
bool |
logic | True, False |
# Create one of each
age = 27 # int
temperature = 98.6 # float
greeting = "Hello" # str
is_student = True # bool
# Inspect values and types
print(age, type(age))
print(temperature, type(temperature))
print(greeting, type(greeting))
print(is_student, type(is_student))
27 <class 'int'> 98.6 <class 'float'> Hello <class 'str'> True <class 'bool'>
Basic operations¶
- numbers —
+ - * / // % ** - strings —
+joins,*repeats - booleans — produced by comparisons
## Code — Arithmetic with int/float
a = 10 # int
b = 3 # int
c = 2.5 # float
d = a + b
print("a + b =", d)
print("a / b =", a / b) # float division
print("a // b =", a // b) # integer (floor) division
print("a ** b =", a ** b) # exponent
print("b * c =", b * c) # int * float → float
a + b = 13 a / b = 3.3333333333333335 a // b = 3 a ** b = 1000 b * c = 7.5
Strings¶
Single or double quotes: "Alice", 'Python is fun!'
+concatenates,*repeats- methods:
.lower(),.upper(),.replace()
### Code — Basic string examples
name = "Ada"
greeting = "Hello, " + name + "!"
print(greeting)
# String methods
message = "Data Science"
print(message.lower())
print(message.upper())
print(message.replace("Science", "Analysis"))
Hello, Ada! data science DATA SCIENCE Data Analysis
## Code — Strings (str)
first = "Ada"
last = "Lovelace"
full = first + " " + last # concatenation: joining strings together
print("Full name:", full)
print("Repeat:", "ha" * 3) # repetition
# f-string: readable string formatting
score = 95.2
print(first, "scored", score, "on the quiz")
print(f"{first} scored {score} on the quiz.")
Full name: Ada Lovelace Repeat: hahaha Ada scored 95.2 on the quiz Ada scored 95.2 on the quiz.
f-strings¶
Put f before the quote; anything inside {} is evaluated.
f"{name} scored {score:.1f}%"
Easier to read than gluing pieces with +.
## Code — Booleans (bool) from comparisons
x = 7
y = 10
print("x < y:", x < y)
print("x == y:", x == y)
print("x != y:", x != y)
name = "Ada"
print("Name starts with A:", name.startswith("A"))
x < y: True x == y: False x != y: True Name starts with A: True
Type conversion¶
int(), float(), str() convert between types.
# Number to string
n = 42
print(type(n))
print("As string:", str(n), type(str(n)))
# String to number (must be numeric!)
num_str = "3.14"
print("As float:", float(num_str), type(float(num_str)))
# Boolean from comparison
passed = 87 >= 60
print("Passed?", passed, type(passed))
<class 'int'> As string: 42 <class 'str'> As float: 3.14 <class 'float'> Passed? True <class 'bool'>
Three gotchas¶
=assigns,==compares0.1 + 0.2gives0.30000000000000004— useround(x, 2)for display- strings always need quotes
val = 0.1 + 0.2
print("Raw:", val)
print("Rounded to 2 decimals:", round(val, 2))
Raw: 0.30000000000000004 Rounded to 2 decimals: 0.3
Why 0.1 + 0.2 isn't 0.3¶
Floats are stored in binary (IEEE-754). Neither 0.1 nor 0.2 has an exact binary form — same problem as writing 1/3 in decimal — so the sum carries a tiny rounding error.
Exercises 1¶
- Create four variables: age (
int), temperature (float), first name (str), likes coffee (bool). - With
base = 12andheight = 7.5, print the triangle area using an f-string. - True or false?
"Data".lower() == "data"·len("abc") == 3·int("10") > 5
Lists, tuples, dictionaries¶
| type | mutable | ordered | syntax | example |
|---|---|---|---|---|
| list | yes | yes | [ ] |
["apple", "banana"] |
| tuple | no | yes | ( ) |
(10, 20) |
| dict | yes | by key | { } |
{"name": "Ada"} |
List — ordered and changeable. Square brackets.
fruits = ["apple", "banana", "cherry"]
print("All fruits:", fruits)
print("First fruit:", fruits[1]) # first item
fruits.append("date") # add new item
print("After adding:", fruits)
All fruits: ['apple', 'banana', 'cherry'] First fruit: banana After adding: ['apple', 'banana', 'cherry', 'date']
Tuple — same idea, but fixed once created. Parentheses. Use for things that shouldn't change, like a coordinate pair.
coords = (10, 20)
print("Coordinates:", coords)
# coords[0] = 15 # ❌ This would cause an error (immutable)
Coordinates: (10, 20)
Dictionary — key–value pairs. Label data by name ("age") instead of position (1).
student = {"name": "Ada", "age": 23, "major": "Math"}
print(student)
print("Student name:", student["name"])
student["age"] = 24
print("Updated age:", student["age"])
{'name': 'Ada', 'age': 23, 'major': 'Math'}
Student name: Ada
Updated age: 24
# One dictionary, each key stores multiple values (as a list)
students = {
"name": ["Alice", "Bob"],
"age": [24, 27],
"major": ["Economics", "Mathematics"]
}
print(students)
Indexing and slicing¶
Zero-based: x[0] is first, x[-1] is last.
Slices are x[start:end] — the end is excluded.
nums = [10, 20, 30, 40, 50]
print("First three:", nums[:3])
print("Middle:", nums[1:4])
print("Every other number:", nums[::2])
print("Reversed:", nums[::-1])
First three: [10, 20, 30] Middle: [20, 30, 40] Every other number: [10, 30, 50] Reversed: [50, 40, 30, 20, 10]
Exercises 2¶
course = "Python Workshop"— printlen(course).- Make a list of three cities, add a fourth, print the first and last.
- Build a dict
personwith name, age, hobby — print only the hobby.
Functions and modules¶
Functions¶
def name(parameters):
return value
Parameters carry information in, return sends a value back out. Write once, reuse everywhere.
### First function + parameters + return
def greet(name):
"""Return a friendly greeting for the given name."""
return f"Hello, {name}!"
msg = greet("Ada")
print(msg)
Hello, Ada!
Reading def greet(name):
defstarts the definition,greetis the name,nameis a parameter- the
"""docstring"""on the next line documents it — read it later withhelp(greet)
Modules¶
A module is a file of ready-made code you import.
math— square roots, trigonometry, πdatetime— dates, formatting, differences
import math
math.sqrt(16)
import statistics as stats
vals = [2, 4, 4, 4, 5, 5, 7, 9]
print("Mean:", stats.mean(vals))
print("Median:", stats.median(vals))
print("Stdev:", round(stats.stdev(vals), 3))
Mean: 5 Median: 4.5 Stdev: 2.138
Import selectively to pull in only what you need:
from math import sqrt
Shorter to type and explicit about what you use. Explore any module with help(math) or help(math.sqrt).
from datetime import date, timedelta
today = date.today()
print(today)
tomorrow = today + timedelta(days=1) # creates a one-day time difference, then adding it to today shifts the date forward by one day
print("Tomorrow:", tomorrow)
2025-11-03 Tomorrow: 2025-11-04
Visualization¶
- plot with
matplotlib - build a line plot and a bar chart
- add titles, axis labels, legends
Matplotlib¶
The base plotting library — seaborn and others build on it.
import matplotlib.pyplot as plt
### Simple line plot
import matplotlib.pyplot as plt
# Example data
years = ["2020", "2021", "2022", "2023", "2024"]
sales = [250, 300, 400, 350, 500]
# Create a line plot
plt.plot(years, sales, marker='o', label='Annual Sales')
# Add title, labels, legend
plt.title("Company Sales Over Time")
plt.xlabel("Year")
plt.ylabel("Sales (in $K)")
plt.legend()
plt.grid(True)
plt.show()
Bar chart¶
Best for comparing categories.
categories = ["Apples", "Bananas", "Cherries", "Dates"]
values = [50, 75, 30, 90]
plt.bar(categories, values, color="skyblue")
plt.title("Fruit Sales")
plt.xlabel("Fruit Type")
plt.ylabel("Units Sold")
plt.show()
Mini project · The Phillips curve¶
Real data, start to finish:
- pull two series from FRED
- clean and merge them with pandas
- summary statistics and a correlation
- plot inflation against unemployment
1 · Setup¶
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
import pandas_datareader.data as web
2 · Load the FRED data¶
CPIAUCSL— Consumer Price Index, seasonally adjusted (a level, not a rate)UNRATE— unemployment rate, percent
We convert CPI into year-over-year inflation.
# Define date range (feel free to adjust)
start = datetime(2015, 1, 1)
end = datetime(2025, 12, 31)
# Read series from FRED
cpi = web.DataReader("CPIAUCSL", "fred", start, end)
print(cpi.head())
unr = web.DataReader("UNRATE", "fred", start, end)
print(unr.head())
# Compute year-over-year inflation rate (%)
cpi['Inflation'] = cpi['CPIAUCSL'].pct_change(12) * 100
print(cpi.head())
# Merge on date index
df = pd.concat([cpi['Inflation'], unr['UNRATE']], axis=1).dropna()
df.columns = ['Inflation', 'Unemployment']
df.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 116 entries, 2016-01-01 to 2025-08-01 Freq: MS Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Inflation 116 non-null float64 1 Unemployment 116 non-null float64 dtypes: float64(2) memory usage: 2.7 KB
What the code does¶
datetime(Y, M, D)sets the date range.web.DataReader(symbol, "fred", start, end)fetches each series, indexed by date.pct_change(12)takes the 12-month change; ×100 makes it percent. The first 12 rows areNaN.$\text{Inflation}_t = \dfrac{CPI_t - CPI_{t-12}}{CPI_{t-12}} \times 100$
pd.concat(..., axis=1)merges on the shared date index;dropna()clears the leadingNaNs.
Needs pip install pandas-datareader.
3 · Summary statistics and correlation¶
print("Summary statistics:")
display(df.describe())
corr = df['Inflation'].corr(df['Unemployment']) # Pearson correlation by default
print(f"Correlation between Inflation and Unemployment: {corr:.3f}")
Summary statistics:
| Inflation | Unemployment | |
|---|---|---|
| count | 116.000000 | 116.000000 |
| mean | 3.150491 | 4.587069 |
| std | 2.127807 | 1.753235 |
| min | 0.198201 | 3.400000 |
| 25% | 1.731757 | 3.700000 |
| 50% | 2.481514 | 4.100000 |
| 75% | 3.382786 | 4.700000 |
| max | 8.999298 | 14.800000 |
Correlation between Inflation and Unemployment: -0.362
4 · Trends over time¶
One plot per series, for clarity.
# Inflation over time
plt.figure()
plt.plot(df.index, df['Inflation'])
plt.title("Inflation Rate")
plt.xlabel("Year")
plt.ylabel("Percent")
plt.grid(True)
plt.tight_layout()
plt.show()
# Unemployment over time
plt.figure()
plt.plot(df.index, df['Unemployment'])
plt.title("Unemployment Rate (%)")
plt.xlabel("Year")
plt.ylabel("Percent")
plt.grid(True)
plt.tight_layout()
plt.show()
5 · The Phillips curve¶
Inflation (y) against unemployment (x), with a least-squares line from numpy.polyfit.
x = df['Unemployment'].to_numpy()
y = df['Inflation'].to_numpy()
# Linear fit: y = m*x + b
m, b = np.polyfit(x, y, 1) # np.polyfit with degree=1 returns slope m and intercept b (least squares)
# creates 100 evenly spaced points from a to b to draw a smooth fitted line.
line_x = np.linspace(x.min(), x.max(), 100)
line_y = m * line_x + b
plt.figure()
plt.scatter(x, y, alpha=0.6, label="Monthly observations")
plt.plot(line_x, line_y, label=f"OLS fit: y = {m:.2f}x + {b:.2f}")
plt.title("Phillips Curve: Inflation vs. Unemployment")
plt.xlabel("Unemployment Rate (%)")
plt.ylabel("Inflation Rate (YoY, %)")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
np.polyfit(x, y, 1)returns slopem— inflation change per 1pp of unemployment — and interceptbnp.linspace(a, b, 100)gives evenly spaced points to draw the fitted linealpha=0.6keeps dense clusters readable;tight_layout()fixes label spacing
