| Title: | Add Smoothing Spline Modelling Capability to `nlme` |
|---|---|
| Description: | Adds smoothing spline modelling capability to nlme. Fits smoothing spline terms in Gaussian linear and nonlinear mixed-effects models. |
| Authors: | Rod Ball [aut], Andrzej T. Galecki [cre] (ORCID: <https://orcid.org/0000-0003-1542-4001>) |
| Maintainer: | Andrzej T. Galecki <[email protected]> |
| License: | GPL (>= 2) |
| Version: | 1.1.20 |
| Built: | 2026-05-28 10:52:59 UTC |
| Source: | https://github.com/agalecki/lmesplines |
Interpolates the Z-matrix for LME smoothing spline fits from one set of time covariate values to another using linear interpolation of each column of the Z-matrix, regarded as a function of time.
approx.Z(Z, oldtimes, newtimes)approx.Z(Z, oldtimes, newtimes)
Z |
Z-matrix with rows corresponding to the sorted unique values of the
time covariate (e.g., from |
oldtimes |
Numeric vector of original (sorted) time covariate values
corresponding to the rows of |
newtimes |
Numeric vector of new time covariate values to interpolate to. |
A matrix with the same number of columns as Z and rows
corresponding to newtimes, containing the interpolated Z-matrix values.
This can be used with smspline for fitting LME splines with
random effects at different time points or as part of the newdata
argument in predict.lme for predictions at new points.
Linear interpolation works well because the spline basis functions are approximately piecewise linear.
Rod Ball <[email protected]>
times1 <- 1:10 Zt1 <- smspline(~ times1) times2 <- seq(1, 10, by = 0.1) Zt2 <- approx.Z(Zt1, oldtimes = times1, newtimes = times2)times1 <- 1:10 Zt1 <- smspline(~ times1) times2 <- seq(1, 10, by = 0.1) Zt2 <- approx.Z(Zt1, oldtimes = times1, newtimes = times2)
Functions to generate matrices for a smoothing spline covariance structure,
enabling the fitting of smoothing spline terms in linear mixed-effects models
(LME) or nonlinear mixed-effects models (NLME). A smoothing spline can be
represented as a mixed model, as described by Speed (1991) and Verbyla (1999).
The generated Z-matrix can be incorporated into a data frame and used in LME
random effects terms with an identity covariance structure
(pdIdent(~Z - 1)).
The model formulation for a spline in time (t) is:
where , , and
is a set of random effects. The random effects are
transformed to independence via , where
and is the lower triangle of the
Cholesky decomposition of . The Z-matrix is transformed to
.
smspline(formula, data) smspline.v(time)smspline(formula, data) smspline.v(time)
formula |
Model formula with the right-hand side specifying the spline
covariate (e.g., |
data |
Optional data frame containing the variable specified in
|
time |
Numeric vector of spline time covariate values to smooth over. |
For smspline, a Z-matrix with the same number of rows as the input data
frame or vector, representing the random effects design matrix for the
smoothing spline. After fitting an LME model, the standard deviation parameter
for the random effects estimates , and the smoothing parameter
is .
For smspline.v, a list containing:
Matrix for fixed effects, with columns [1 | t].
Matrix for random effects, computed as Q (t(Q) %*% Q)^-1 L.
Matrix used in the spline formulation.
Covariance matrix for the random effects.
Cholesky factor of Gs.
The time points for the smoothing spline basis are, by default, the unique
values of the time covariate. Model predictions at the fitted data points can
be obtained using predict.lme. For predictions at different time points,
use approx.Z to interpolate the Z-matrix.
Rod Ball <[email protected]>
Pinheiro, J. and Bates, D. (2000) Mixed-Effects Models in S and S-PLUS. Springer-Verlag, New York.
Speed, T. (1991) Discussion of "That BLUP is a good thing: the estimation of random effects" by G. Robinson. Statistical Science, 6, 42–44.
Verbyla, A. (1999) Mixed Models for Practitioners. Biometrics SA, Adelaide.
# Smoothing spline curve fit data(smSplineEx1) smSplineEx1$all <- rep(1, nrow(smSplineEx1)) smSplineEx1$Zt <- smspline(~ time, data = smSplineEx1) fit1s <- lme(y ~ time, data = smSplineEx1, random = list(all = pdIdent(~ Zt - 1))) summary(fit1s) plot(smSplineEx1$time, smSplineEx1$y, pch = "o", type = "n", main = "Spline fits: lme(y ~ time, random = list(all = pdIdent(~ Zt - 1)))", xlab = "time", ylab = "y") points(smSplineEx1$time, smSplineEx1$y, col = 1) lines(smSplineEx1$time, smSplineEx1$y.true, col = 1) lines(smSplineEx1$time, fitted(fit1s), col = 2) # Fit model with reduced number of spline points times20 <- seq(1, 100, length = 20) Zt20 <- smspline(times20) smSplineEx1$Zt20 <- approx.Z(Zt20, times20, smSplineEx1$time) fit1s20 <- lme(y ~ time, data = smSplineEx1, random = list(all = pdIdent(~ Zt20 - 1))) anova(fit1s, fit1s20) summary(fit1s20) # Model predictions on a finer grid times200 <- seq(1, 100, by = 0.5) pred.df <- data.frame(all = rep(1, length(times200)), time = times200) pred.df$Zt20 <- approx.Z(Zt20, times20, times200) yp20.200 <- predict(fit1s20, newdata = pred.df) lines(times200, yp20.200 + 0.02, col = 4) # Mixed model spline terms at multiple levels of grouping data(Spruce) Spruce$Zday <- smspline(~ days, data = Spruce) Spruce$all <- rep(1, nrow(Spruce)) spruce.fit1 <- lme(logSize ~ days, data = Spruce, random = list(all = pdIdent(~ Zday - 1), plot = ~ 1, Tree = ~ 1)) spruce.fit2 <- lme(logSize ~ days, data = Spruce, random = list(all = pdIdent(~ Zday - 1), plot = pdBlocked(list(~ days, pdIdent(~ Zday - 1))), Tree = ~ 1)) anova(spruce.fit1, spruce.fit2) summary(spruce.fit1)# Smoothing spline curve fit data(smSplineEx1) smSplineEx1$all <- rep(1, nrow(smSplineEx1)) smSplineEx1$Zt <- smspline(~ time, data = smSplineEx1) fit1s <- lme(y ~ time, data = smSplineEx1, random = list(all = pdIdent(~ Zt - 1))) summary(fit1s) plot(smSplineEx1$time, smSplineEx1$y, pch = "o", type = "n", main = "Spline fits: lme(y ~ time, random = list(all = pdIdent(~ Zt - 1)))", xlab = "time", ylab = "y") points(smSplineEx1$time, smSplineEx1$y, col = 1) lines(smSplineEx1$time, smSplineEx1$y.true, col = 1) lines(smSplineEx1$time, fitted(fit1s), col = 2) # Fit model with reduced number of spline points times20 <- seq(1, 100, length = 20) Zt20 <- smspline(times20) smSplineEx1$Zt20 <- approx.Z(Zt20, times20, smSplineEx1$time) fit1s20 <- lme(y ~ time, data = smSplineEx1, random = list(all = pdIdent(~ Zt20 - 1))) anova(fit1s, fit1s20) summary(fit1s20) # Model predictions on a finer grid times200 <- seq(1, 100, by = 0.5) pred.df <- data.frame(all = rep(1, length(times200)), time = times200) pred.df$Zt20 <- approx.Z(Zt20, times20, times200) yp20.200 <- predict(fit1s20, newdata = pred.df) lines(times200, yp20.200 + 0.02, col = 4) # Mixed model spline terms at multiple levels of grouping data(Spruce) Spruce$Zday <- smspline(~ days, data = Spruce) Spruce$all <- rep(1, nrow(Spruce)) spruce.fit1 <- lme(logSize ~ days, data = Spruce, random = list(all = pdIdent(~ Zday - 1), plot = ~ 1, Tree = ~ 1)) spruce.fit2 <- lme(logSize ~ days, data = Spruce, random = list(all = pdIdent(~ Zday - 1), plot = pdBlocked(list(~ days, pdIdent(~ Zday - 1))), Tree = ~ 1)) anova(spruce.fit1, spruce.fit2) summary(spruce.fit1)
Simulated dataset to demonstrate smoothing spline curve fitting with
smspline and lme. The data consists of 100
observations simulated around the curve with
independent normal random errors (standard deviation = 1).
Simulated dataset to demonstrate smoothing spline curve fitting with
smspline and lme. The data consists of 100
observations simulated around the curve with
independent normal random errors (standard deviation = 1).
smSplineEx1 smSplineEx1smSplineEx1 smSplineEx1
A data frame with 100 rows and 3 variables:
Time covariate.
Simulated response values.
True response values.
A data frame with 100 rows and 3 variables:
Time covariate.
Simulated response values.
True response values.
Generated by Rod Ball for the lmeSplines package.
data(smSplineEx1) str(smSplineEx1) data(smSplineEx1) str(smSplineEx1) plot(smSplineEx1$time, smSplineEx1$y, main = "Simulated Data", xlab = "Time", ylab = "y") lines(smSplineEx1$time, smSplineEx1$y.true, col = "blue")data(smSplineEx1) str(smSplineEx1) data(smSplineEx1) str(smSplineEx1) plot(smSplineEx1$time, smSplineEx1$y, main = "Simulated Data", xlab = "Time", ylab = "y") lines(smSplineEx1$time, smSplineEx1$y.true, col = "blue")