We utilize the package fdapace
(Gajardo et al. 2021) to showcase the completion
of simulated functional fragments when one has available a densely
observed sample of curves (Carroll et al.
2020).
### Simulate functional fragments
set.seed(1)
# set parameters for simulation
<- 50 # number of sample trajectories
n <- 30 # number of observation per curve
m <- seq(0, 1, len = m) # set up regular grid
grid <- 3^(-(2*(1:25)-1)) # eigenvalues
lambda.cos <- 3^(-(2*(1:25)))
lambda.sin <- 0.25 # proportion of domain missing
mpct <- ((1:100) - .5)/100 # dense regular grid to generate the data
densegr <- densegr[(100/m)*(1:m)] # observation grid
gr <- 0.1 # variance for noise term
sigma2
# generate discretely observed complete functional data
<- matrix(0, n, length(densegr))
x.full for (j in 1:length(lambda.cos)) {
<- sqrt(lambda.cos[j])*sqrt(2)*cos(2*pi*(2*j - 1)*densegr)
f <- x.full + rnorm(n, 0, 1)%*%t(f)
x.full
}for (j in 1:length(lambda.sin)) {
<- sqrt(lambda.sin[j])*sqrt(2)*sin(2*pi*(2*j)*densegr)
f <- x.full + rnorm(n, 0, 1)%*%t(f)
x.full
}
# subset the original dense true curve to the k-equidistance sampling scheme;
<- x.full[, densegr %in% gr]
x
# generate observation periods by deleting a random subinterval from domain,
# with 20% of data is complete
# matrix of indicators for inclusion/exclusion of observation
<- matrix(1, n, length(grid))
x.obs <- c(0.25, 0.5, 0.75)
centers 1, ] <- grid <= 0.75
x.obs[for (i in floor(n*0.2):n) {
<- runif(1)
cen - mpct/2 < grid)&(grid < cen + mpct/2)] <- FALSE
x.obs[i, (cen # missing interval = (cen-u,cen+u)
}# remove missing periods
!x.obs] <- NA
x[
# distort by error term
for(i in 1:dim(x)[1]){
for(j in 1:dim(x)[2]){
<- x[i,j] + rnorm(n = 1, sd = sqrt(sigma2))
x[i,j]
} }
# visualize the functional fragments
matplot(gr, t(x[c(1, 9:15), ]), type="l", lty=c(1, 1, 2, 2, 2, 2, 2, 2),
xlab="", ylab="")
title(sub = 'Figure 1: Error-contaminated observations from functional fragments.',
line = 2)
### Use FPCA to complete the missing fragments
# convert x matrix into 3 vectors
<- c()
id <- c()
time <- c()
y for(i in 1:n){
<- append(id, rep(i, sum(x.obs[i, ])))
id <- append(time, grid[x.obs[i, ] == 1])
time <- append(y, x[i, x.obs[i,] == 1])
y
}<- MakeFPCAInputs(IDs = id, tVec = time, y)
L3 <- list(dataType = 'Sparse', usergrid = TRUE, methodXi = 'CE')
optns <- FPCA(L3$Ly, L3$Lt, optns = optns)
fit # completed trajectory for the 1st test sample
<- as.vector(predict(fit, newLy = L3$Ly[1], newLt = L3$Lt[1],
PACE.pred K = fit$selectK, xiMethod = "CE")$predCurves)
# Visualize and compare the observations, true trajectory and completed trajectory
# scatterplot of original data with missing parts
matplot(gr, x[1, ], pch = c(16), col = 1, xlab = "", ylab = "", ylim = c(-2, 2))
lines(grid, PACE.pred, lty = 1, col = 2, xlab = "", ylab = "")# completed functional data
lines(densegr, x.full[1, ], col = 3)# discretely observed complete functional data
legend("topleft", legend = c("discretedly observed data", "completed trajectory",
"true trajectory"),
bty = "n", lty = c(NA, 1, 1), pch = c(16, NA, NA), col = 1:3)
title(sub = 'Figure 2: PACE completion for functional fragments with 25% of
subinterval missing.', line = 3)