Teaching notebooks for the Brainard Lab. Every notebook can be run in the browser with Google Colab — no local install required.
Any notebook in this repo opens in Colab through a URL of this form:
https://colab.research.google.com/github/BrainardLab/PythonTeachingCode/blob/main/<path-to-notebook>.ipynb
Or browse interactively: open https://colab.research.google.com, choose
GitHub, enter BrainardLab/PythonTeachingCode, and pick a notebook.
Colab gives each session a fresh, temporary machine. Changes are not saved back to GitHub. To keep your edits use File → Save a copy in Drive, or File → Download → .ipynb.
Notebooks in notebooks/key/lecture_3.2/:
| Notebook | Open in Colab |
|---|---|
| lecture_3.2_Group_A.ipynb — in-class predict-then-plot, pooled Group A height game | |
| StockChangeDistribution.ipynb — daily S&P 500 moves (fat tails) | |
| HeightDistribution.ipynb — adult women's height, NHANES (nicely normal) | |
| CityPopulationDistribution.ipynb — US city sizes, raw and log10 (lognormal) |
StockChangeDistribution, HeightDistribution, and CityPopulationDistribution
each compare a real data set against a normal distribution using the same
plots and summary table. The shared code lives in
notebooks/key/lecture_3.2/dist_tools.py;
each notebook only loads its data, wraps it in a dist_tools.Distribution, and
calls dist_tools.analyze(). Edit dist_tools.py once and all three notebooks
change together. Each notebook downloads dist_tools.py from GitHub at run time
when it isn't already present, so Colab works with no extra steps.
tools/build_notebooks.py regenerates the three notebooks' shared scaffolding.
Notebooks in notebooks/key/lab_W4/:
| Notebook | Open in Colab |
|---|---|
| False_Positives_Negatives.ipynb — interactive digital companion for the Week 4 lab on false positives/negatives: adjustable decision-threshold sliders show how the four outcome counts and error rates change |
Notebooks in notebooks/key/lectures_5.1_5.2/:
| Notebook | Open in Colab |
|---|---|
| SpuriousCorrelations.ipynb — correlation vs. causation, five real spurious correlations (margarine/divorce, UFOs/patents, school enrollment/BofA stock, baby names/stock price, movie roles/electricity) replotted from tylervigen.com, a source-verification summary, one example extended with real current data, and a deliberately arbitrary (not cherry-picked) pairing testing whether two unrelated variables still show a "significant" correlation | |
| NFLRegressionToTheMean.ipynb — regression to the mean in NFL team records, 1999–2025: each team's win fraction plotted against the season before, built up step by step (dots, "same as last year" line, best-fit line, red and black stars) in win fractions and in standard units, then binned conditional means, then news stories that credit or blame coaches (Nagy, Daboll, O'Connell, Johnson, Vrabel) shown against the regression line. Data read at run time from nflverse | |
MLBBattingRegressionToTheMean.ipynb — regression to the mean in MLB batting averages, 1961–2025: the same step-by-step sequence as the NFL notebook, plus the SD line, the reversed plot (year N−1 against year N, so regression runs backward in time too), a two-chimney plot (hitters about +1 SD in year N−1 in red, in year N in green, in both in yellow), a coin-flip model showing chance alone predicts the year-to-year correlation, the batting-champion "curse" and sophomore slump (including José Abreu, 2015) against the regression line, and histograms locating the 2024 batting champions in both seasons. Data: SABR Lahman Baseball Database (CC BY-SA 3.0), in data/ |
|
DINKIncome.ipynb — "dual income, no kids" married couples in Pennsylvania: family income against the wife's earnings, then husband's against wife's earnings, which correlate weakly overall (r ≈ 0.18) but strongly negatively (r ≈ −0.99) once family income is restricted to $150K–$160K, shown alone and in red among all couples. Data: US Census Bureau American Community Survey 2024 PUMS (public domain), in data/ |
|
| NHANESHeightWeightRegression.ipynb — weight against height for men 18 and over (NHANES 2015–2018, read from the CDC): the same step-by-step sequence with the SD line in place of "same as last year", a star-by-star build-up of the SD line, single-bin and all-bin conditional means (including a bin centered at +1 SD), and the reversed plot predicting height from weight; regression to the mean with no time, luck, or story involved |
The four regression and conditioning notebooks (NFL, MLB, DINK, NHANES) are
generated by scripts in tools/ (build_nfl_regression.py,
build_mlb_regression.py, build_dink_income.py,
build_nhanes_height_weight.py), so edit the script rather than the
notebook, then rebuild, re-badge and execute:
python tools/build_mlb_regression.py
python tools/add_colab_badge.py notebooks/key/lectures_5.1_5.2/MLBBattingRegressionToTheMean.ipynb
jupyter nbconvert --to notebook --execute --inplace notebooks/key/lectures_5.1_5.2/MLBBattingRegressionToTheMean.ipynbThe MLB and DINK notebooks read small data files from
notebooks/key/lectures_5.1_5.2/data/,
whose README gives each file's source, license and columns.
tools/make_mlb_batting_data.py and tools/make_dink_data.py rebuild those
files from the original downloads. On Colab these notebooks fetch the data
from GitHub, so the data files must be pushed for the Colab links to work.
-
Put the
.ipynbfile anywhere undernotebooks/. If a script intools/generates it, add or edit the script instead and run it. -
Run
python tools/add_colab_badge.pyto insert an "Open in Colab" badge as the first cell (idempotent — safe to re-run on every notebook; it recurses into subfolders). -
Add a row to a table above.
-
Commit and push:
git add notebooks/ tools/ README.md git commit -m "Add your_notebook" git push
The pushed notebook is immediately runnable in Colab via its badge link.
Use a current Python (3.12 matches Colab). On macOS, a bare python3 may be
Apple's Command Line Tools Python 3.9, so name the version explicitly
(e.g. brew install python@3.12).
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt jupyterlab
jupyter labrequirements.txt lists only what the notebooks import; JupyterLab (or
VS Code's notebook support) is needed to open them.