# 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()](../reference/list_datasets.md#whittaker.list_datasets) returns metadata for every built-in dataset:


``` python
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()](../reference/load_dataset.md#whittaker.load_dataset) returns a column-oriented dictionary that can be passed directly to [GAM.fit()](../reference/GAM.md#whittaker.GAM.fit):


``` python
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


``` python
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):


``` python
df = wk.load_dataset("wages", as_frame=True)
df.head()
```


<style>
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,600;1,400&family=IBM+Plex+Sans:wght@400;600&display=swap');
#gd-tbl-d828d22c .gt_table {
  display: table;
  border-collapse: collapse;
  table-layout: fixed;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 14px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
}
#gd-tbl-d828d22c .gt_heading {
  background-color: #FFFFFF;
  text-align: left;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-right-style: none;
}
#gd-tbl-d828d22c .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}
#gd-tbl-d828d22c .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}
#gd-tbl-d828d22c .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}
#gd-tbl-d828d22c .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-right-style: none;
}
#gd-tbl-d828d22c .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: solid;
  border-left-width: 1px;
  border-left-color: #F2F2F2;
  border-right-style: solid;
  border-right-width: 1px;
  border-right-color: #F2F2F2;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}
#gd-tbl-d828d22c .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
}
#gd-tbl-d828d22c .gt_row {
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #E9E9E9;
  border-left-style: solid;
  border-left-width: 1px;
  border-left-color: #E9E9E9;
  border-right-style: solid;
  border-right-width: 1px;
  border-right-color: #E9E9E9;
  vertical-align: middle;
  overflow-x: hidden;
}
#gd-tbl-d828d22c .gt_left { text-align: left; }
#gd-tbl-d828d22c .gt_center { text-align: center; }
#gd-tbl-d828d22c .gt_right { text-align: right; font-variant-numeric: tabular-nums; }
#gd-tbl-d828d22c .gt_font_normal { font-weight: normal; }
#gd-tbl-d828d22c .gt_font_bold { font-weight: bold; }
#gd-tbl-d828d22c .gt_font_italic { font-style: italic; }
#gd-tbl-d828d22c .gt_striped { background-color: rgba(128,128,128,0.05); }
#gd-tbl-d828d22c .gt_from_md > :first-child { margin-top: 0; }
#gd-tbl-d828d22c .gt_from_md > :last-child { margin-bottom: 0; }
/* Data cell font */
#gd-tbl-d828d22c .gt_table_body .gt_row {
  font-family: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: #333333;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  height: 14px;
}
/* Column label font */
#gd-tbl-d828d22c .gt_col_heading {
  font-family: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: #333333;
}
/* Row number styling */
#gd-tbl-d828d22c .gd-tbl-rownum {
  color: gray;
  font-family: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  border-right: 2px solid rgba(102, 153, 204, 0.5) !important;
  text-align: right;
  padding-right: 6px;
  white-space: nowrap;
}
/* Head/tail divider */
#gd-tbl-d828d22c tr.gd-tbl-divider td,
#gd-tbl-d828d22c tr.gd-tbl-divider th {
  border-bottom: 2px solid rgba(102, 153, 204, 0.5);
}
/* Missing values */
#gd-tbl-d828d22c .gd-tbl-missing {
  color: #B22222 !important;
  background-color: rgba(255, 193, 193, 0.35);
}
/* Column label sub-elements */
#gd-tbl-d828d22c .gd-tbl-colname {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  padding-bottom: 0;
  margin-bottom: 0;
}
#gd-tbl-d828d22c .gd-tbl-dtype {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  padding-top: 0;
  margin-top: 0;
  color: #666666;
}
/* Header badge styling */
#gd-tbl-d828d22c .gd-tbl-badge {
  display: inline-block;
  padding: 2px 10px;
  font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 10px;
  font-weight: bold;
  text-transform: uppercase;
  position: inherit;
}
#gd-tbl-d828d22c .gd-tbl-badge-rows-label {
  background-color: #eecbff;
  color: #333333;
  border: 1px solid #eecbff;
  margin-left: 5px;
}
#gd-tbl-d828d22c .gd-tbl-badge-rows-value {
  background-color: transparent;
  color: #333333;
  border: 1px solid #eecbff;
  margin-left: -4px;
  margin-right: 3px;
}
#gd-tbl-d828d22c .gd-tbl-badge-cols-label {
  background-color: #BDE7B4;
  color: #333333;
  border: 1px solid #BDE7B4;
}
#gd-tbl-d828d22c .gd-tbl-badge-cols-value {
  background-color: transparent;
  color: #333333;
  border: 1px solid #BDE7B4;
  margin-left: -4px;
}
/* Dark mode */
body.quarto-dark #gd-tbl-d828d22c .gt_table,
html.quarto-dark #gd-tbl-d828d22c .gt_table,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_table {
  background-color: #1a1a2e;
  color: #e0e0e0;
  border-top-color: #555;
  border-bottom-color: #555;
}
body.quarto-dark #gd-tbl-d828d22c .gt_heading,
html.quarto-dark #gd-tbl-d828d22c .gt_heading,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_heading {
  background-color: #1a1a2e;
  border-bottom-color: #1a1a2e;
}
body.quarto-dark #gd-tbl-d828d22c .gt_title,
html.quarto-dark #gd-tbl-d828d22c .gt_title,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_title {
  color: #e0e0e0;
}
body.quarto-dark #gd-tbl-d828d22c .gt_subtitle,
html.quarto-dark #gd-tbl-d828d22c .gt_subtitle,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_subtitle {
  color: #b0b0b0;
}
body.quarto-dark #gd-tbl-d828d22c .gt_col_headings,
html.quarto-dark #gd-tbl-d828d22c .gt_col_headings,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_col_headings {
  border-top-color: #444;
  border-bottom-color: #444;
}
body.quarto-dark #gd-tbl-d828d22c .gt_col_heading,
html.quarto-dark #gd-tbl-d828d22c .gt_col_heading,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_col_heading {
  color: #b0b0b0;
  background-color: #1a1a2e;
  border-left-color: #333;
  border-right-color: #333;
}
body.quarto-dark #gd-tbl-d828d22c .gt_table_body,
html.quarto-dark #gd-tbl-d828d22c .gt_table_body,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_table_body {
  border-top-color: #444;
}
body.quarto-dark #gd-tbl-d828d22c .gt_table_body .gt_row,
html.quarto-dark #gd-tbl-d828d22c .gt_table_body .gt_row,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_table_body .gt_row {
  color: #d0d0d0;
  border-top-color: #4b4b4b;
  border-bottom-color: #4b4b4b;
  border-left-color: #333;
  border-right-color: #333;
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-rownum,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-rownum,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-rownum {
  color: #888;
  border-right-color: rgba(102, 153, 204, 0.4) !important;
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-missing,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-missing,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-missing {
  color: #ff6b6b !important;
  background-color: rgba(60, 17, 24, 0.2);
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-dtype,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-dtype,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-dtype {
  color: #888;
}
body.quarto-dark #gd-tbl-d828d22c .gt_bottom_border,
html.quarto-dark #gd-tbl-d828d22c .gt_bottom_border,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gt_bottom_border {
  border-bottom-color: #555;
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-rows-label,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-rows-label,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-badge-rows-label {
  background-color: #3d2a4d;
  border-color: #3d2a4d;
  color: #e0c0ff;
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-rows-value,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-rows-value,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-badge-rows-value {
  border-color: #3d2a4d;
  color: #d0b0e0;
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-cols-label,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-cols-label,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-badge-cols-label {
  background-color: #2a4d2a;
  border-color: #2a4d2a;
  color: #b0e0b0;
}
body.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-cols-value,
html.quarto-dark #gd-tbl-d828d22c .gd-tbl-badge-cols-value,
:root[data-bs-theme="dark"] #gd-tbl-d828d22c .gd-tbl-badge-cols-value {
  border-color: #2a4d2a;
  color: #a0d0a0;
}
</style>

<table class="gt_table" data-quarto-disable-processing="true" data-quarto-bootstrap="false">
<thead>
<tr class="gt_heading">
<th colspan="4" class="gt_heading gt_title gt_font_normal"><div style="padding-top: 0; padding-bottom: 7px;">
<span class="gd-tbl-badge" style="background-color: #150458; color: #FFFFFF; border: 1px solid #150458; margin-right: 8px;">Pandas</span>Rows5Columns3
</div></th>
</tr>
<tr class="gt_col_headings">
<th class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"></th>
<th id="age" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

age

<em>f64</em>

</div></th>
<th id="experience" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

experience

<em>f64</em>

</div></th>
<th id="wage" class="gt_col_heading gt_columns_bottom_border gt_right" scope="col"><div>

wage

<em>f64</em>

</div></th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr>
<td class="gt_row gt_right gd-tbl-rownum">0</td>
<td class="gt_row gt_right" style="max-width: 155px">62.3236369619</td>
<td class="gt_row gt_right" style="max-width: 155px">9.21681747511</td>
<td class="gt_row gt_right" style="max-width: 155px">80.2312228265</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">1</td>
<td class="gt_row gt_right" style="max-width: 155px">42.0323949823</td>
<td class="gt_row gt_right" style="max-width: 155px">2.48784091836</td>
<td class="gt_row gt_right" style="max-width: 155px">40.0241886358</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">2</td>
<td class="gt_row gt_right" style="max-width: 155px">63.8834541683</td>
<td class="gt_row gt_right" style="max-width: 155px">7.2519118615</td>
<td class="gt_row gt_right" style="max-width: 155px">60.2928515793</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">3</td>
<td class="gt_row gt_right" style="max-width: 155px">21.7992931231</td>
<td class="gt_row gt_right" style="max-width: 155px">3.79929312309</td>
<td class="gt_row gt_right" style="max-width: 155px">20.2329400441</td>
</tr>
<tr>
<td class="gt_row gt_right gd-tbl-rownum">4</td>
<td class="gt_row gt_right" style="max-width: 155px">46.5457241038</td>
<td class="gt_row gt_right" style="max-width: 155px">1.73811889414</td>
<td class="gt_row gt_right" style="max-width: 155px">62.3832136627</td>
</tr>
</tbody>
</table>


# 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.


``` python
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.


``` python
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.


``` python
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.


``` python
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.


``` python
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.


``` python
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.


``` python
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.


``` python
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.


``` python
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.


``` python
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%


> **Tip: GAMLSS with the climate dataset**
>
> For the full location-scale analysis, see [Distributional regression (GAMLSS)](gamlss.md), which models both the mean and variance as smooth functions of the predictors.


# Where to go next

- **[Quick start](quick-start.md)**: fitting your first model.
- **[Response families](families.md)**: choosing the right family for your data.
- **[Data input](data-input.md)**: using your own data with pandas, polars, or pyarrow.
