Built-in datasets

Whittaker ships with 10 synthetic datasets covering a range of response families and modeling scenarios. They are generated with fixed random seeds, so they are fully reproducible without internet access or optional dependencies. Use them for quick demonstrations, testing, and learning.

Listing available datasets

list_datasets() returns metadata for every built-in dataset:

import whittaker as wk

for ds in wk.list_datasets():
    print(f"{ds['name']:>14}  {ds['family']:<12}  {ds['description']}")
        mcycle  Gaussian      Simulated motorcycle-crash accelerometer data (n=133).
           co2  Gaussian      Synthetic monthly atmospheric CO2 concentrations (n=504, 1958–1999).
          fish  Poisson       Synthetic fish-count survey data (n=300).
        credit  Binomial      Synthetic credit-default dataset (n=1000).
         wages  Gamma         Synthetic worker-earnings dataset (n=800).
   proportions  Beta          Synthetic seed-germination dataset (n=400).
         meuse  Gaussian      Synthetic river-bank heavy-metals dataset (n=155).
      survival  CoxPH         Synthetic clinical-trial survival dataset (n=250).
       abalone  Gaussian      Synthetic abalone morphology dataset (n=500).
       climate  GaussianLS    Synthetic climate station dataset (n=600).

Each entry includes the dataset name, a short description, the intended response family, the variables it contains, and a note about what modeling scenario it illustrates.

Loading a dataset

load_dataset() returns a column-oriented dictionary that can be passed directly to GAM.fit():

data = wk.load_dataset("mcycle")

print(f"Type: {type(data)}")
print(f"Keys: {list(data.keys())}")
print(f"Observations: {len(data['times'])}")
Type: <class 'dict'>
Keys: ['times', 'accel']
Observations: 133
model = wk.GAM("accel ~ s(times)").fit(data)
model.summary()
GAM fit summary
============================================================
Formula:    accel ~ s(times)
Family:     Gaussian(link='identity')
Inference:  GCV
Observations: 133
Coefficients: 10

Parametric coefficients:
  Term                       Estimate    Std.Err    t value    p-value
  ------------------------ ---------- ---------- ---------- ----------
  (Intercept)                -45.6924     1.8364    -24.882    < 1e-16

Approximate significance of smooth terms:
  Term                        EDF Ref.df     Chi.sq    p-value
  ------------------------ ------ ------ ---------- ----------
  s(times)                   7.92      8    663.396    < 1e-16

Total EDF:  8.92
Scale est:  448.517253
Deviance:   55653.7152
Null dev:   357878.4929
Dev. expl:  84.4%
GCV score:  480.746119
AIC:        1198.44
BIC:        1224.22

Loading as a DataFrame

Pass as_frame=True to get a pandas DataFrame instead (requires pandas):

df = wk.load_dataset("wages", as_frame=True)
df.head()
PandasRows5Columns3
age
f64
experience
f64
wage
f64
0 62.3236369619 9.21681747511 80.2312228265
1 42.0323949823 2.48784091836 40.0241886358
2 63.8834541683 7.2519118615 60.2928515793
3 21.7992931231 3.79929312309 20.2329400441
4 46.5457241038 1.73811889414 62.3832136627

Dataset catalog

mcycle — Gaussian, heteroscedastic

Simulated motorcycle-crash accelerometer data (n=133). Head acceleration measured at various times after impact. Strongly non-linear and heteroscedastic — a standard stress test for smoothing.

data = wk.load_dataset("mcycle")
model = wk.GAM("accel ~ s(times)").fit(data)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 8.9, Dev. explained: 84.4%

co2 — Gaussian, trend + seasonal

Synthetic monthly CO2 concentrations (n=504, 1958–1999) with a rising trend and annual cycle. Good for cyclic smooths and additive decomposition.

data = wk.load_dataset("co2")
model = wk.GAM("co2 ~ s(t) + s(month, bs='cc', k=12)").fit(data, method="REML")
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 16.5, Dev. explained: 100.0%

fish — Poisson counts

Fish-abundance survey (n=300) with a hump-shaped temperature effect and a linear depth effect.

from whittaker.families.poisson import Poisson

data = wk.load_dataset("fish")
model = wk.GAM("count ~ s(temperature) + s(depth)", family=Poisson()).fit(data)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 7.0, Dev. explained: 62.0%

credit — Binomial (binary)

Credit-default dataset (n=1000) with smooth effects of income and debt ratio on default probability.

from whittaker.families.binomial import Binomial

data = wk.load_dataset("credit")
model = wk.GAM("default ~ s(income) + s(debt_ratio) + s(age)", family=Binomial()).fit(data)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 8.1, Dev. explained: 16.7%

wages — Gamma

Worker-earnings dataset (n=800) with log-wages shaped by smooth age and experience effects.

from whittaker.families.gamma import Gamma

data = wk.load_dataset("wages")
model = wk.GAM("wage ~ s(age) + s(experience)", family=Gamma()).fit(data)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 7.1, Dev. explained: 78.2%

proportions — Beta

Seed-germination dataset (n=400) with a bounded [0, 1] response and a non-linear temperature optimum.

from whittaker.families.beta import Beta

data = wk.load_dataset("proportions")
model = wk.GAM("germination_rate ~ s(temperature) + s(water)", family=Beta()).fit(data)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 7.8, Dev. explained: 65.5%

meuse — Gaussian, spatial

River-bank heavy-metals dataset (n=155) with map coordinates. Log(zinc) decreases with distance from the river. Good for 2D spatial smooths.

import numpy as np

data = wk.load_dataset("meuse")
data["log_zinc"] = np.log(data["zinc"])
model = wk.GAM("log_zinc ~ s(x, y) + s(dist)").fit(data, method="REML")
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 3.0, Dev. explained: 61.8%

survival — Cox PH

Clinical-trial survival dataset (n=250) with a smooth age effect and a binary treatment arm. Approximately 30% censored.

from whittaker.families.cox_ph import CoxPH

data = wk.load_dataset("survival")
model = wk.GAM("time ~ s(age) + treatment", family=CoxPH(status="event")).fit(data)
print(f"EDF: {model.goodness_of_fit().edf_total:.1f}")
EDF: 3.1

abalone — Gaussian, multi-predictor

Abalone morphology dataset (n=500) with four predictors and a ring count response. Good for tensor products and multi-term additive models.

data = wk.load_dataset("abalone")
model = wk.GAM("rings ~ s(length) + s(shucked_weight)").fit(data)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 11.4, Dev. explained: 82.7%

climate — GaussianLS (location-scale)

Climate station dataset (n=600) where both the mean and variance of temperature depend on altitude and latitude. Designed for GAMLSS location-scale modeling.

data = wk.load_dataset("climate")
model = wk.GAM("temperature ~ s(altitude) + s(latitude) + s(month, bs='cc', k=12)").fit(
    data, method="REML"
)
gof = model.goodness_of_fit()
print(f"EDF: {gof.edf_total:.1f}, Dev. explained: {gof.deviance_explained:.1%}")
EDF: 9.5, Dev. explained: -19.9%
TipGAMLSS with the climate dataset

For the full location-scale analysis, see Distributional regression (GAMLSS), which models both the mean and variance as smooth functions of the predictors.

Where to go next