---
name: Generalized Additive Models
description: "GAM standards using mgcv in R. Use when fitting gam(), specifying smooth terms, selecting basis types, or diagnosing concurvity."
metadata:
  labels: [statistical-computing, gam, mgcv, smooth, model-selection]
  triggers:
    files: ['**/*.R']
    keywords: ["gam(", mgcv, "s(", "te(", smooth, REML, concurvity, GCV]
---

# Generalized Additive Models

## **Priority: P1 (OPERATIONAL)**

## 🏗 Core Structure

```r
library(mgcv)
model <- gam(outcome ~ s(x1) + s(x2) + factor_var,
             family = quasipoisson(), data = df, method = "REML")
```

## 📐 Smooth Terms

| Term | Usage | Description |
|---|---|---|
| `s(x)` | Univariate smooth | Thin plate spline by default |
| `s(x, bs = "cr")` | Cubic regression spline | Faster, good for medium data |
| `s(x, bs = "ps")` | P-spline | Good for penalized DLNM |
| `te(x1, x2)` | Tensor product | Full interaction (separate smoothing per dimension) |
| `ti(x1, x2)` | Tensor interaction | Pure interaction (main effects excluded) |
| `s(x, k = 10)` | Set basis dimension | `k` sets max wiggliness (default: 10) |

## 🎯 Basis Types

| `bs =` | Name | Best For |
|---|---|---|
| `"tp"` | Thin plate (default) | General purpose, isotropic |
| `"cr"` | Cubic regression | Faster computation, 1D |
| `"ps"` | P-spline | DLNM penalty integration |
| `"cc"` | Cyclic cubic | Seasonal effects (circular) |
| `"re"` | Random effect | Random intercepts/slopes |

## ⚙️ Smoothing Parameter Selection

- **REML** (Recommended): `method = "REML"` — most stable, less prone to under-smoothing.
- **GCV.Cp**: `method = "GCV.Cp"` — faster but can under-smooth.
- **ML**: `method = "ML"` — for model comparison with `AIC()`.

## 🔍 Diagnostics

```r
# Check basis dimension adequacy
gam.check(model)    # k-index < 1 suggests k is too low

# Concurvity (collinearity for smooths)
concurvity(model, full = TRUE)   # > 0.8 is concerning

# Summary with effective df
summary(model)      # edf ≈ 1 means nearly linear
```

## 🔗 Integration with DLNM

- **Penalized DLNM**: Use `gam()` with `paraPen = list(cb = cbPen(cb))`.
- **Mixed models**: Combine `s()` smooths for confounders with parametric cross-basis.
- **Prediction**: `crosspred()` works with both `glm()` and `gam()` objects.

## 🚫 Common Mistakes

- **Low `k`**: If `gam.check()` says basis dimension is too low, increase `k`.
- **Wrong `bs` for DLNM**: Use `"cr"` or `"ps"` with `cbPen()`, not `"tp"`.
- **Ignoring concurvity**: High concurvity between time smooth and exposure can bias estimates.

## 📚 References

- [GAM Cookbook](references/GAM_COOKBOOK.md)
- Wood 2017 (*Generalized Additive Models: An Introduction with R*)
