Predicting pig weight from repeated field measurements, using additive and mixed-effects models that respect the longitudinal structure of the data.
Each animal is weighed and measured week after week, so its observations are not independent — a fact that ordinary regression ignores and that drives every modelling choice made here. The project works through kernel regression, GAMs, linear mixed-effects models and finally GAMMs, comparing them on information criteria, residual diagnostics and out-of-sample error.
Statistical modelling project — ENSIIE, 2024–2025.
170 pigs across 7 farms, measured weekly from 8 August to 25 December 2020 (11–20 observations per animal).
| Column | Description |
|---|---|
NumberID |
Unique animal identifier — the grouping variable for random effects |
ID |
Animal number within its farm |
Farm |
Farm identifier (1–7) |
Species |
Breed code (1–3) |
Gender |
Gender code (1–2) |
Day |
Measurement date |
Age |
Age in weeks (3–25) |
Weight |
Response — body weight in kg |
Chest |
Chest girth in cm |
Length |
Body length in cm |
The train/test split is by animal: the 142 training pigs and the 28 test pigs are disjoint, so test error measures generalization to unseen animals rather than to unseen weeks of familiar ones.
Missing data. Chest and Length are absent from ~51% of rows while
Weight is complete. Dropping those rows would discard half the dataset, so
they are imputed with MICE (predictive mean matching, m = 5, seed 42). The
imputed files carry two extra bookkeeping columns, .imp and .id.
.
├── analysis/
│ ├── 01_exploratory_analysis.Rmd # EDA, missing-data handling, MICE imputation
│ └── 02_growth_models.Rmd # kernel regression, GAM, LME, GAMM, evaluation
├── data/
│ ├── raw/ # train.csv, test.csv — as collected
│ └── processed/ # *_imputed.csv — output of notebook 01
└── R/
└── install_dependencies.R # one-shot package installer
Notebook 01 writes the files in data/processed/; notebook 02 reads them.
Requires R ≥ 4.0 (RStudio recommended).
Rscript R/install_dependencies.RThen knit the notebooks in order — from RStudio's Knit button, or from the command line:
Rscript -e 'rmarkdown::render("analysis/01_exploratory_analysis.Rmd")'
Rscript -e 'rmarkdown::render("analysis/02_growth_models.Rmd")'Paths inside the notebooks are relative to analysis/, which is both knitr's
default and RStudio's default for chunk evaluation. The MICE and GAMM chunks
are cached, so only the first knit pays their full cost.
1 — Exploration and imputation. Herd composition, individual growth trajectories, correlations between physical measurements, and IQR-based outlier detection applied within species × farm groups. Missing measurements are filled by multiple imputation.
2 — Modelling. Five families, in increasing order of structure:
| Model | What it adds |
|---|---|
Kernel regression (sm) |
Assumption-free view of the age–weight curve, with a 95% variability band |
GAM (mgcv) |
Smooth non-linear covariate effects; effective degrees of freedom test whether linearity suffices |
LME (lme4) |
Random intercept and random slope per animal, absorbing between-pig variability |
LME + AR(1) (nlme) |
Residual correlation that decays with the gap between measurements |
GAMM (mgcv) |
Smooth fixed effects and random effects together |
Models are compared on log-likelihood, AIC/BIC, Q-Q and residual-versus-fitted plots, and RMSE on the held-out animals — overall and broken down by age.
- Weight grows nearly linearly with age, but the spread does not: it is narrow for piglets, widest between weeks 15 and 20, and narrows again by week 25. Animals begin their growth spurt at different times, so the herd fans out during growth and closes up once most have reached adult weight.
- Effective degrees of freedom above 1 confirm the age effect is genuinely non-linear — a smooth term beats a plain linear slope.
Weight,ChestandLengthare strongly correlated, so individual coefficients should be read with collinearity in mind.- A random effect on
NumberIDis essential; adding an AR(1) residual structure refines it further. - GAMM gives the best balance of fit and interpretability. Three variants
perform comparably: random intercept, random intercept with an
Age:Chestinteraction, and random intercept with AR(1) errors. - Residual diagnostics support the retained models — residuals centred on zero, normal Q-Q plots, no clear heteroscedasticity.
- Predictions stay reliable to roughly 15–20 weeks of age, after which error grows along with the dispersion of the herd.
- Stacked imputations. The processed files stack all five MICE completions,
and notebook 02 fits on that stacked file by default. This inflates the
effective sample size fivefold and makes standard errors optimistic; the
rigorous alternative is to fit per completion and pool with Rubin's rules.
A
USE_SINGLE_IMPUTATIONswitch at the top of notebook 02 restricts the fit to one completion. - Species and gender are provided as anonymous integer codes, so breed-level findings cannot be tied back to named breeds.
Farmis treated as a fixed grouping; with only seven farms, a random effect at that level would be weakly identified.
R · mgcv · lme4 · nlme · mice · sm · ggplot2 · dplyr ·
lattice · R Markdown