Nothing
# --------------------------------------------------------------------
# Gait data
# --------------------------------------------------------------------
# --------------------------------------------------------------------
#
# Overview of the analyses
#
# The gait data were chosen for these sample analyses because they are
# bivariate: consisting of both hip and knee angles observed over a
# gait cycle for 39 children. The bivariate nature of the data implies
# certain displays and analyses that are not usually considered, and
# especially the use of canonical correlation analysis.
#
# As with the daily weather data, the harmonic acceleration roughness
# penalty is used throughout since the data are periodic with a strong
# sinusoidal component of variation.
#
# After setting up the data, smoothing the data using GCV (generalized
# cross-validation) to select a smoothing parameter, and displaying
# various descriptive results, the data are subjected to a principal
# components analysis, followed by a canonical correlation analysis of
# thejoint variation of hip and knee angle, and finally a registration
# of the curves. The registration is included here especially because
# the registering of periodic data requires the estimation of a phase
# shift constant for each curve in addition to possible nonlinear
# transformations of time.
#
# --------------------------------------------------------------------
# Last modified 10 November 2010 by Jim Ramsay
# attach the FDA functions
library(fda)
# Set up the argument values: equally spaced over circle of
# circumference 20. Earlier analyses of the gait data used time
# values over [0,1], but led to singularity problems in the use of
# function fRegress. In general, it is better use a time interval
# that assigns roughly one time unit to each inter-knot interval.
gaittime <- as.matrix((0:19)+0.5)
gaitrange <- c(0,20)
# display ranges of gait for each variable
apply(gait, 3, range)
# ----------- set up the harmonic acceleration operator ----------
harmaccelLfd <- vec2Lfd(c(0, (2*pi/20)^2, 0), rangeval=gaitrange)
# Set up basis for representing gait data. The basis is saturated
# since there are 20 data points per curve, and this set up defines
# 21 basis functions. Recall that a fourier basis has an odd number
# of basis functions.
gaitbasis <- create.fourier.basis(gaitrange, nbasis=21)
# -------------------------------------------------------------------
# Choose level of smoothing using
# the generalized cross-validation criterion
# -------------------------------------------------------------------
# set up range of smoothing parameters in log_10 units
gaitLoglam <- seq(-4,0,0.25)
nglam <- length(gaitLoglam)
gaitSmoothStats <- array(NA, dim=c(nglam, 3),
dimnames=list(gaitLoglam, c("log10.lambda", "df", "gcv") ) )
gaitSmoothStats[, 1] <- gaitLoglam
# loop through smoothing parameters
for (ilam in 1:nglam) {
gaitSmooth <- smooth.basisPar(gaittime, gait, gaitbasis,
Lfdobj=harmaccelLfd, lambda=10^gaitLoglam[ilam])
gaitSmoothStats[ilam, "df"] <- gaitSmooth$df
gaitSmoothStats[ilam, "gcv"] <- sum(gaitSmooth$gcv)
# note: gcv is a matrix in this case
}
# display and plot GCV criterion and degrees of freedom
gaitSmoothStats
plot(gaitSmoothStats[, 1], gaitSmoothStats[, 3])
# set up plotting arrangements for one and two panel displays
# allowing for larger fonts
op <- par(mfrow=c(2,1))
plot(gaitLoglam, gaitSmoothStats[, "gcv"], type="b",
xlab="Log_10 lambda", ylab="GCV Criterion",
main="Gait Smoothing", log="y")
plot(gaitLoglam, gaitSmoothStats[, "df"], type="b",
xlab="Log_10 lambda", ylab="Degrees of freedom",
main="Gait Smoothing")
par(op)
# With gaittime <- (1:20)/21,
# GCV is minimized with lambda = 10^(-2).
gaitfd <- smooth.basisPar(gaittime, gait,
gaitbasis, Lfdobj=harmaccelLfd, lambda=1e-2)$fd
names(gaitfd$fdnames) <- c("Normalized time", "Child", "Angle")
gaitfd$fdnames[[3]] <- c("Hip", "Knee")
str(gaitfd)
# -------- plot curves and their first derivatives ----------------
#par(mfrow=c(1,2), mar=c(3,4,2,1), pty="s")
op <- par(mfrow=c(2,1))
plot(gaitfd, cex=1.2)
par(op)
# plot each pair of curves interactively
plotfit.fd(gait, gaittime, gaitfd, cex=1.2, ask=FALSE)
# plot the residuals, sorting cases by residual sum of squares
# this produces 39 plots for each of knee and hip angle
plotfit.fd(gait, gaittime, gaitfd, residual=TRUE, sort=TRUE, cex=1.2)
# plot first derivative of all curves
op <- par(mfrow=c(2,1))
plot(gaitfd, Lfdobj=1)
par(op)
# -----------------------------------------------------------------
# Display the mean, variance and covariance functions
# -----------------------------------------------------------------
# ------------ compute the mean functions --------------------
gaitmeanfd <- mean.fd(gaitfd)
# plot these functions and their first two derivatives
op <- par(mfcol=2:3)
plot(gaitmeanfd)
plot(gaitmeanfd, Lfdobj=1)
plot(gaitmeanfd, Lfdobj=2)
par(op)
# -------------- Compute the variance functions -------------
gaitvarbifd <- var.fd(gaitfd)
str(gaitvarbifd)
gaitvararray <- eval.bifd(gaittime, gaittime, gaitvarbifd)
# plot variance and covariance functions as contours
filled.contour(gaittime, gaittime, gaitvararray[,,1,1], cex=1.2)
title("Knee - Knee")
filled.contour(gaittime, gaittime, gaitvararray[,,1,2], cex=1.2)
title("Knee - Hip")
filled.contour(gaittime, gaittime, gaitvararray[,,1,3], cex=1.2)
title("Hip - Hip")
# plot variance and covariance functions as surfaces
persp(gaittime, gaittime, gaitvararray[,,1,1], cex=1.2)
title("Knee - Knee")
persp(gaittime, gaittime, gaitvararray[,,1,2], cex=1.2)
title("Knee - Hip")
persp(gaittime, gaittime, gaitvararray[,,1,3], cex=1.2)
title("Hip - Hip")
# plot correlation functions as contours
gaitCorArray <- cor.fd(gaittime, gaitfd)
quantile(gaitCorArray)
contour(gaittime, gaittime, gaitCorArray[,,1,1], cex=1.2)
title("Knee - Knee")
contour(gaittime, gaittime, gaitCorArray[,,1,2], cex=1.2)
title("Knee - Hip")
contour(gaittime, gaittime, gaitCorArray[,,1,3], cex=1.2)
title("Hip - Hip")
# --------------------------------------------------------------
# Principal components analysis
# --------------------------------------------------------------
# do the PCA with varimax rotation
# Smooth with lambda as determined above
gaitfdPar <- fdPar(gaitbasis, harmaccelLfd, lambda=1e-2)
gaitpca.fd <- pca.fd(gaitfd, nharm=4, gaitfdPar)
gaitpca.fd <- varmx.pca.fd(gaitpca.fd)
# plot harmonics using cycle plots
op <- par(mfrow=c(2,2))
plot.pca.fd(gaitpca.fd, cycle=TRUE)
par(op)
# compute proportions of variance associated with each angle
gaitharmmat = eval.fd(gaittime, gaitpca.fd$harmonics)
hipharmmat = gaitharmmat[,,1]
kneeharmmat = gaitharmmat[,,2]
# then we want to find the total size of each
hipharmL2 = apply(hipharmmat^2,2,mean)
kneeharmL2 = apply(kneeharmmat^2,2,mean)
hippropvar2 = hipharmL2/(hipharmL2+kneeharmL2)
kneepropvar2 = 1-hippropvar2
print("Percentages of fits for the PCA:")
print(round(100*cbind(hippropvar2, kneepropvar2),1))
# --------------------------------------------------------------
# Canonical correlation analysis
# --------------------------------------------------------------
hipfd <- gaitfd[,1]
kneefd <- gaitfd[,2]
hipfdPar <- fdPar(hipfd, harmaccelLfd, 1e2)
kneefdPar <- fdPar(kneefd, harmaccelLfd, 1e2)
ccafd <- cca.fd(hipfd, kneefd, ncan=3, hipfdPar, kneefdPar)
# plot the canonical weight functions
op <- par(mfrow=c(2,1), mar=c(3,4,2,1), pty="m")
plot.cca.fd(ccafd, cex=1.2)
par(op)
# display the canonical correlations
round(ccafd$ccacorr[1:6],3)
plot(1:6, ccafd$ccacorr[1:6], type="b")
# --------------------------------------------------------------
# Register the angular acceleration of the gait data
# --------------------------------------------------------------
# compute the acceleration and mean acceleration
D2gaitfd <- deriv.fd(gaitfd,2)
names(D2gaitfd$fdnames)[[3]] <- "Angular acceleration"
D2gaitfd$fdnames[[3]] <- c("Hip", "Knee")
D2gaitmeanfd <- mean.fd(D2gaitfd)
names(D2gaitmeanfd$fdnames)[[3]] <- "Mean angular acceleration"
D2gaitmeanfd$fdnames[[3]] <- c("Hip", "Knee")
# set up basis for warping function
nwbasis <- 7
wbasis <- create.bspline.basis(gaitrange,nwbasis,3)
Warpfd <- fd(matrix(0,nwbasis,5),wbasis)
WarpfdPar <- fdPar(Warpfd)
# register the functions
gaitreglist <- register.fd(D2gaitmeanfd, D2gaitfd[1:5,], WarpfdPar, periodic=TRUE)
plotreg.fd(gaitreglist)
# display horizonal shift values
print(round(gaitreglist$shift,1))
# histogram of horizontal shift values
par(mfrow=c(1,1))
hist(gaitreglist$shift,xlab="Normalized time")
# --------------------------------------------------------------
# Predict knee angle from hip angle
# for angle and angular acceleration
# --------------------------------------------------------------
# set up the data
hipfd <- gaitfd[,1]
kneefd <- gaitfd[,2]
ncurve <- dim(kneefd$coefs)[2]
kneemeanfd <- mean(kneefd)
# define the functional parameter object for regression functions
betafdPar <- fdPar(gaitbasis, harmaccelLfd)
betalist <- list(betafdPar,betafdPar)
# ---------- predict knee angle from hip angle --------
conbasis <- create.constant.basis(c(0,20))
constfd <- fd(matrix(1,1,ncurve), conbasis)
# set up the list of covariate objects
xfdlist <- list(constfd, hipfd)
# fit the current functional linear model
fRegressout <- fRegress(kneefd, xfdlist, betalist)
# set up and plot the fit functions and the regression functions
kneehatfd <- fRegressout$yhatfd
betaestlist <- fRegressout$betaestlist
alphafd <- betaestlist[[1]]$fd
hipbetafd <- betaestlist[[2]]$fd
op <- par(mfrow=c(2,1), ask=FALSE)
plot(alphafd, ylab="Intercept")
plot(hipbetafd, ylab="Hip coefficient")
par(op)
# compute and plot squared multiple correlation function
gaitfine <- seq(0,20,len=101)
kneemat <- eval.fd(gaitfine, kneefd)
kneehatmat <- predict(kneehatfd, gaitfine)
kneemeanvec <- as.vector(eval.fd(gaitfine, kneemeanfd))
SSE0 <- apply((kneemat - outer(kneemeanvec, rep(1,ncurve)))^2, 1, sum)
SSE1 <- apply((kneemat - kneehatmat)^2, 1, sum)
Rsqr <- (SSE0-SSE1)/SSE0
op <- par(mfrow=c(1,1),ask=FALSE)
plot(gaitfine, Rsqr, type="l", ylim=c(0,0.4))
# for each case plot the function being fit, the fit,
# and the mean function
op <- par(mfrow=c(1,1),ask=TRUE)
for (i in 1:ncurve) {
plot( gaitfine, kneemat[,i], type="l", lty=1, col=4, ylim=c(0,80))
lines(gaitfine, kneemeanvec, lty=2, col=2)
lines(gaitfine, kneehatmat[,i], lty=3, col=4)
title(paste("Case",i))
}
par(op)
# ---------- predict knee acceleration from hip acceleration --------
D2kneefd <- deriv(kneefd, 2)
D2hipfd <- deriv(hipfd, 2)
D2kneemeanfd <- mean(D2kneefd)
# set up the list of covariate objects
D2xfdlist <- list(constfd,D2hipfd)
# fit the current functional linear model
D2fRegressout <- fRegress(D2kneefd, D2xfdlist, betalist)
# set up and plot the fit functions and the regression functions
D2kneehatfd <- D2fRegressout$yhatfd
D2betaestlist <- D2fRegressout$betaestlist
D2alphafd <- D2betaestlist[[1]]$fd
D2hipbetafd <- D2betaestlist[[2]]$fd
op <- par(mfrow=c(2,1), ask=FALSE)
plot(D2alphafd, ylab="D2Intercept")
plot(D2hipbetafd, ylab="D2Hip coefficient")
par(op)
# compute and plot squared multiple correlation function
D2kneemat <- eval.fd(gaitfine, D2kneefd)
D2kneehatmat <- predict(D2kneehatfd, gaitfine)
D2kneemeanvec <- as.vector(eval.fd(gaitfine, D2kneemeanfd))
D2SSE0 <- apply((D2kneemat - outer(D2kneemeanvec, rep(1,ncurve)))^2, 1, sum)
D2SSE1 <- apply((D2kneemat - D2kneehatmat)^2, 1, sum)
D2Rsqr <- (D2SSE0-D2SSE1)/D2SSE0
par(mfrow=c(1,1),ask=FALSE)
plot(gaitfine, D2Rsqr, type="l", ylim=c(0,0.5))
# for each case plot the function being fit, the fit, and the mean function
op <- par(mfrow=c(1,1),ask=TRUE)
for (i in 1:ncurve) {
plot( gaitfine, D2kneemat[,i], type="l", lty=1, col=4, ylim=c(-20,20))
lines(gaitfine, D2kneemeanvec, lty=2, col=2)
lines(gaitfine, D2kneehatmat[,i], lty=3, col=4)
lines(c(0,20), c(0,0), lty=2, col=2)
title(paste("Case",i))
}
par(op)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.