import whittaker as wk
data = wk.load_dataset("proportions", as_frame=True)
data.columns.tolist()['temperature', 'water', 'germination_rate']
Use the Beta family when your response is a rate or proportion that is strictly between 0 and 1 (germination rates, survival fractions, market share, or test pass rates). A Gaussian model can predict values outside (0, 1) and assumes constant variance; Beta regression respects the natural bounds and allows variance to vary with the mean. The logit link means that each covariate has a multiplicative effect on the odds of the proportion.
Load the proportions dataset and inspect its columns.
['temperature', 'water', 'germination_rate']
The dataset contains germination_rate, temperature, and water.
| temperature | water | germination_rate | |
|---|---|---|---|
| 0 | 31.565096 | 14.971623 | 0.627402 |
| 1 | 31.662046 | 42.421705 | 0.834827 |
| 2 | 22.005744 | 39.074516 | 0.994336 |
| 3 | 14.431446 | 54.364739 | 0.991711 |
| 4 | 6.779713 | 20.583531 | 0.738985 |
The response germination_rate is already bounded in (0, 1). Verify this before fitting. The Beta family requires strictly interior values; zeros and ones require a zero-one-inflated extension.
Fit a Beta GAM with smooths over both covariates.
model = wk.GAM(
"germination_rate ~ s(temperature) + s(water)",
family=wk.Beta(),
).fit(data)
model.summary()GAM fit summary
============================================================
Formula: germination_rate ~ s(temperature) + s(water)
Family: Beta(link='logit')
Inference: GCV
Observations: 400
Coefficients: 19
Parametric coefficients:
Term Estimate Std.Err t value p-value
------------------------ ---------- ---------- ---------- ----------
(Intercept) 1.6150 0.0445 36.274 < 1e-16
Approximate significance of smooth terms:
Term EDF Ref.df Chi.sq p-value
------------------------ ------ ------ ---------- ----------
s(temperature) 3.95 4 565.110 < 1e-16
s(water) 2.84 3 66.788 2.079e-14
Total EDF: 7.79
Scale est: 0.084702
Deviance: 33.2210
Null dev: 96.1702
Dev. expl: 65.5%
GCV score: 0.086385
AIC: -873.15
BIC: -842.05
The EDF for each smooth indicates how non-linear the relationship is. An EDF near 1 suggests a roughly logistic (linear on the logit scale) relationship; higher EDF indicates more curvature.
Partial effects are shown on the logit (link) scale. Positive values increase the expected germination rate; negative values decrease it. The shape of each curve reveals whether the effect is monotone or peaks at an intermediate covariate value.
For a Beta model, check that the residuals are roughly symmetric around zero and that there is no strong pattern in the residual-vs-fitted plot. Heteroscedasticity is less concerning here because the Beta family already allows non-constant variance.
Predictions from a Beta GAM are automatically constrained to (0, 1): no transformation needed.
import pandas as pd
# Build new-data over temperature and water values
new_data = pd.DataFrame({
"temperature": [15.0, 20.0, 25.0],
"water": [30.0, 50.0, 70.0],
})
# Predict germination rates with confidence intervals
preds = model.predict(new_data, interval="confidence")
# Assemble results with prediction bounds
pd.DataFrame({
"temperature": new_data["temperature"],
"water": new_data["water"],
"predicted_rate": preds.values,
"lower": preds.lower,
"upper": preds.upper,
})| temperature | water | predicted_rate | lower | upper | |
|---|---|---|---|---|---|
| 0 | 15.0 | 30.0 | 0.884682 | 0.862113 | 0.903969 |
| 1 | 20.0 | 50.0 | 0.947542 | 0.935010 | 0.957767 |
| 2 | 25.0 | 70.0 | 0.947592 | 0.934392 | 0.958255 |
All predicted values and interval bounds are on the (0, 1) scale, directly interpretable as expected germination rates.