Nothing
# Author: Quentin Grimonprez
context("Encoding functions")
## common dataset
set.seed(42)
K <- 4
Tmax <- 10
PJK <- matrix(1 / 3, nrow = K, ncol = K) - diag(rep(1 / 3, K))
lambda_PJK <- c(1, 1, 1, 1)
d_JK <- generate_Markov(n = 10, K = K, P = PJK, lambda = lambda_PJK, Tmax = Tmax)
d_JK2 <- cut_data(d_JK, 10)
##
test_that("compute_Uxij works with a simple basis of 1 function", {
set.seed(42)
m <- 1
# basis with 1 function: constant function = 1 between 0 and T max
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
I <- diag(rep(1, m))
phi <- fd(I, b) # constant function = 1 between 0 and T max
x <- d_JK2[d_JK2$id == 1, ]
out <- compute_Uxij(x, phi, K)
expectedOut <- rep(0, K)
for (i in 1:K) {
idx <- which(x$state == i)
expectedOut[i] <- sum(x$time[idx + 1] - x$time[idx], na.rm = TRUE)
}
expect_length(out, K * m * m)
expect_equal(out, expectedOut)
})
test_that("compute_Uxij works with a simple basis of 2 functions", {
skip_on_cran()
m <- 2
# basis with 2 functions: 1st function: constant = 1 between 0 and Tmax/2 then 0. 2nd function: 0 then 1
I <- diag(rep(1, m))
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
phi <- fd(I, b)
x <- d_JK2[d_JK2$id == 1, ]
out <- compute_Uxij(x, phi, K)
expectedOut <- rep(0, K * m * m)
for (i in 1:K) {
idx <- which(x$state == i)
idx1 <- idx[x$time[idx] <= 5]
expectedOut[1 + (i - 1) * m * m] <- sum(pmin(x$time[idx1 + 1], 5) - x$time[idx1], na.rm = TRUE)
idx2 <- idx[x$time[idx + 1] > 5]
expectedOut[4 + (i - 1) * m * m] <- sum(x$time[idx2 + 1] - pmax(x$time[idx2], 5), na.rm = TRUE)
}
expect_length(out, K * m * m)
expect_lte(max(abs(out - expectedOut)), 1e-5)
})
test_that("compute_integral_U + fillU works with a simple basis of 1 function", {
set.seed(42)
m <- 1
# basis with 1 function: constant function = 1 between 0 and T max
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
I <- diag(rep(1, m))
phi <- fd(I, b) # constant function = 1 between 0 and T max
x <- d_JK2[d_JK2$id == 1, ]
uniqueTime <- sort(unique(d_JK2$time))
index <- data.frame(seq_along(uniqueTime), row.names = uniqueTime)
integrals <- compute_integral_U(phi, uniqueTime, verbose = FALSE)
out <- fill_U(x, integrals, index, K, m)
expectedOut <- rep(0, K)
for (i in 1:K) {
idx <- which(x$state == i)
expectedOut[i] <- sum(x$time[idx + 1] - x$time[idx], na.rm = TRUE)
}
expect_length(out, K * m * m)
expect_equal(out, expectedOut)
})
test_that("compute_integral_U + fillU works with a simple basis of 2 functions", {
skip_on_cran()
m <- 2
# basis with 2 functions: 1st function: constant = 1 between 0 and Tmax/2 then 0. 2nd function: 0 then 1
I <- diag(rep(1, m))
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
phi <- fd(I, b)
x <- d_JK2[d_JK2$id == 1, ]
uniqueTime <- sort(unique(d_JK2$time))
index <- data.frame(seq_along(uniqueTime), row.names = uniqueTime)
integrals <- compute_integral_U(phi, uniqueTime, verbose = FALSE)
out <- fill_U(x, integrals, index, K, m)
expectedOut <- rep(0, K * m * m)
for (i in 1:K) {
idx <- which(x$state == i)
idx1 <- idx[x$time[idx] <= 5]
expectedOut[1 + (i - 1) * m * m] <- sum(pmin(x$time[idx1 + 1], 5) - x$time[idx1], na.rm = TRUE)
idx2 <- idx[x$time[idx + 1] > 5]
expectedOut[4 + (i - 1) * m * m] <- sum(x$time[idx2 + 1] - pmax(x$time[idx2], 5), na.rm = TRUE)
}
expect_length(out, K * m * m)
expect_lte(max(abs(out - expectedOut)), 1e-5)
})
oldcompute_Uxij <- function(x, phi, K) {
nBasis <- phi$basis$nbasis
aux <- rep(0, K * nBasis * nBasis)
for (state in 1:K) {
idx <- which(x$state == state)
for (u in idx) {
for (i in 1:nBasis) {
for (j in 1:nBasis) {
if (u < nrow(x)) {
ind <- (state - 1) * nBasis * nBasis + (i - 1) * nBasis + j
aux[ind] <- aux[ind] +
integrate(
function(t) {
eval.fd(t, phi[i]) * eval.fd(t, phi[j])
},
lower = x$time[u], upper = x$time[u + 1],
stop.on.error = FALSE
)$value
}
}
}
}
}
return(aux)
}
test_that("refactor of compute_Uxij keeps the same results", {
skip_on_cran()
skip_on_ci()
skip_on_covr()
m <- 10
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 4)
I <- diag(rep(1, m))
phi <- fd(I, b)
expectedOut <- by(d_JK2, d_JK2$id, function(x) {
oldcompute_Uxij(x, phi, K)
})
out <- by(d_JK2, d_JK2$id, function(x) {
compute_Uxij(x, phi, K)
})
expect_equal(out[[1]], expectedOut[[1]])
})
test_that("compute_Vxi works with a simple basis of 1 function", {
m <- 1
# basis with 1 function:: constant function = 1 between 0 and T max
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
I <- diag(rep(1, m))
phi <- fd(I, b) # constant function = 1 between 0 and T max
x <- d_JK2[d_JK2$id == 1, ]
out <- compute_Vxi(x, phi, K)
expectedOut <- rep(0, K)
for (i in 1:K) {
idx <- which(x$state == i)
expectedOut[i] <- sum(x$time[idx + 1] - x$time[idx], na.rm = TRUE)
}
expect_length(out, K * m)
expect_equal(out, expectedOut)
})
test_that("compute_Vxi works with a simple basis of 2 functions", {
skip_on_cran()
m <- 2
# basis with 2 functions: 1st function: constant = 1 between 0 and Tmax/2 then 0. 2nd function: 0 then 1
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
I <- diag(rep(1, m))
phi <- fd(I, b)
x <- d_JK2[d_JK2$id == 1, ]
out <- compute_Vxi(x, phi, K)
expectedOut <- rep(0, K * m)
for (i in 1:K) {
idx <- which(x$state == i)
idx1 <- idx[x$time[idx] <= 5]
expectedOut[1 + (i - 1) * m] <- sum(pmin(x$time[idx1 + 1], 5) - x$time[idx1], na.rm = TRUE)
idx2 <- idx[x$time[idx + 1] > 5]
expectedOut[2 + (i - 1) * m] <- sum(x$time[idx2 + 1] - pmax(x$time[idx2], 5), na.rm = TRUE)
}
expect_length(out, K * m)
expect_lte(max(abs(out - expectedOut)), 1e-5)
})
test_that("compute_integral_V + fillV works with a simple basis of 1 function", {
m <- 1
# basis with 1 function:: constant function = 1 between 0 and T max
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
I <- diag(rep(1, m))
phi <- fd(I, b) # constant function = 1 between 0 and T max
x <- d_JK2[d_JK2$id == 1, ]
uniqueTime <- sort(unique(d_JK2$time))
index <- data.frame(seq_along(uniqueTime), row.names = uniqueTime)
integrals <- compute_integral_V(phi, uniqueTime, verbose = FALSE)
out <- fill_V(x, integrals, index, K, m)
expectedOut <- rep(0, K)
for (i in 1:K) {
idx <- which(x$state == i)
expectedOut[i] <- sum(x$time[idx + 1] - x$time[idx], na.rm = TRUE)
}
expect_length(out, K * m)
expect_equal(out, expectedOut)
})
test_that("compute_integral_V + fillV works with a simple basis of 2 functions", {
skip_on_cran()
m <- 2
# basis with 2 functions: 1st function: constant = 1 between 0 and Tmax/2 then 0. 2nd function: 0 then 1
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 1)
I <- diag(rep(1, m))
phi <- fd(I, b)
x <- d_JK2[d_JK2$id == 1, ]
uniqueTime <- sort(unique(d_JK2$time))
index <- data.frame(seq_along(uniqueTime), row.names = uniqueTime)
integrals <- compute_integral_V(phi, uniqueTime, verbose = FALSE)
out <- fill_V(x, integrals, index, K, m)
expectedOut <- rep(0, K * m)
for (i in 1:K) {
idx <- which(x$state == i)
idx1 <- idx[x$time[idx] <= 5]
expectedOut[1 + (i - 1) * m] <- sum(pmin(x$time[idx1 + 1], 5) - x$time[idx1], na.rm = TRUE)
idx2 <- idx[x$time[idx + 1] > 5]
expectedOut[2 + (i - 1) * m] <- sum(x$time[idx2 + 1] - pmax(x$time[idx2], 5), na.rm = TRUE)
}
expect_length(out, K * m)
expect_lte(max(abs(out - expectedOut)), 1e-5)
})
test_that("computeVmatrix keeps the id order", {
all_dat_P1S1 <- data.frame(state = c(1, 2, 1), time = c(0, 0.5, 1), id = rep("P1S1", 3))
all_dat_P1S2 <- data.frame(state = c(1, 2, 1), time = c(0, 0.4, 1), id = rep("P1S2", 3))
all_dat_P1S3 <- data.frame(state = c(1, 2, 1), time = c(0, 0.6, 1), id = rep("P1S3", 3))
all_dat_P2S1 <- data.frame(state = c(1, 3, 1), time = c(0, 0.5, 1), id = rep("P2S1", 3))
all_dat_P2S2 <- data.frame(state = c(1, 3, 1), time = c(0, 0.4, 1), id = rep("P2S2", 3))
all_dat_P2S3 <- data.frame(state = c(1, 3, 1), time = c(0, 0.6, 1), id = rep("P2S3", 3))
all_dat_P3S1 <- data.frame(state = c(3, 1, 1), time = c(0, 0.5, 1), id = rep("P3S1", 3))
all_dat_P3S2 <- data.frame(state = c(3, 1, 1), time = c(0, 0.4, 1), id = rep("P3S2", 3))
all_dat_P3S3 <- data.frame(state = c(3, 1, 1), time = c(0, 0.6, 1), id = rep("P3S3", 3))
# Original dataset
all_dat_a <- rbind(
all_dat_P1S1, all_dat_P1S2, all_dat_P1S3,
all_dat_P2S1, all_dat_P2S2, all_dat_P2S3,
all_dat_P3S1, all_dat_P3S2, all_dat_P3S3
)
all_dat_b <- rbind(
all_dat_P2S1, all_dat_P2S2, all_dat_P2S3,
all_dat_P3S1, all_dat_P3S2, all_dat_P3S3,
all_dat_P1S1, all_dat_P1S2, all_dat_P1S3
)
uniqueIdA <- unique(all_dat_a$id)
uniqueIdB <- unique(all_dat_b$id)
basisobj <- create.bspline.basis(c(0, 1), nbasis = 6, norder = 1)
Va <- computeVmatrix(all_dat_a, basisobj, K = 3, uniqueId = uniqueIdA, nCores = 1, verbose = FALSE)
Vb <- computeVmatrix(all_dat_b, basisobj, K = 3, uniqueId = uniqueIdB, nCores = 1, verbose = FALSE)
expect_equal(nrow(Va), 9)
expect_equal(ncol(Va), 6 * 3)
expect_equal(nrow(Vb), 9)
expect_equal(ncol(Vb), 6 * 3)
expect_equal(Va, Vb[c(7, 8, 9, 1, 2, 3, 4, 5, 6), ])
})
test_that("computeUmatrix keeps the id order", {
all_dat_P1S1 <- data.frame(state = c(1, 2, 1), time = c(0, 0.5, 1), id = rep("P1S1", 3))
all_dat_P1S2 <- data.frame(state = c(1, 2, 1), time = c(0, 0.4, 1), id = rep("P1S2", 3))
all_dat_P1S3 <- data.frame(state = c(1, 2, 1), time = c(0, 0.6, 1), id = rep("P1S3", 3))
all_dat_P2S1 <- data.frame(state = c(1, 3, 1), time = c(0, 0.5, 1), id = rep("P2S1", 3))
all_dat_P2S2 <- data.frame(state = c(1, 3, 1), time = c(0, 0.4, 1), id = rep("P2S2", 3))
all_dat_P2S3 <- data.frame(state = c(1, 3, 1), time = c(0, 0.6, 1), id = rep("P2S3", 3))
all_dat_P3S1 <- data.frame(state = c(3, 1, 1), time = c(0, 0.5, 1), id = rep("P3S1", 3))
all_dat_P3S2 <- data.frame(state = c(3, 1, 1), time = c(0, 0.4, 1), id = rep("P3S2", 3))
all_dat_P3S3 <- data.frame(state = c(3, 1, 1), time = c(0, 0.6, 1), id = rep("P3S3", 3))
# Original dataset
all_dat_a <- rbind(
all_dat_P1S1, all_dat_P1S2, all_dat_P1S3,
all_dat_P2S1, all_dat_P2S2, all_dat_P2S3,
all_dat_P3S1, all_dat_P3S2, all_dat_P3S3
)
all_dat_b <- rbind(
all_dat_P2S1, all_dat_P2S2, all_dat_P2S3,
all_dat_P3S1, all_dat_P3S2, all_dat_P3S3,
all_dat_P1S1, all_dat_P1S2, all_dat_P1S3
)
uniqueIdA <- unique(all_dat_a$id)
uniqueIdB <- unique(all_dat_b$id)
basisobj <- create.bspline.basis(c(0, 1), nbasis = 6, norder = 1)
Ua <- computeUmatrix(all_dat_a, basisobj, K = 3, uniqueId = uniqueIdA, nCores = 1, verbose = FALSE)
Ub <- computeUmatrix(all_dat_b, basisobj, K = 3, uniqueId = uniqueIdB, nCores = 1, verbose = FALSE)
expect_equal(nrow(Ua), 9)
expect_equal(ncol(Ua), 6 * 6 * 3)
expect_equal(nrow(Ub), 9)
expect_equal(ncol(Ub), 6 * 6 * 3)
expect_equal(Ua, Ub[c(7, 8, 9, 1, 2, 3, 4, 5, 6), ])
})
test_that("compute_optimal_encoding throws error", {
set.seed(42)
# create basis object
m <- 10
b <- create.bspline.basis(c(0, 1), nbasis = m, norder = 4)
expect_error(compute_optimal_encoding(d_JK2, 3, nCores = 1, verbose = TRUE), regexp = "basisobj is not a basis object.")
expect_error(compute_optimal_encoding(d_JK2, b, nCores = 0, verbose = TRUE), regexp = "nCores must be an integer > 0.")
expect_error(compute_optimal_encoding(d_JK2, b, nCores = 2.5, verbose = TRUE), regexp = "nCores must be an integer > 0.")
expect_error(compute_optimal_encoding(d_JK2, b, nCores = NA, verbose = TRUE), regexp = "nCores must be an integer > 0.")
expect_error(compute_optimal_encoding(d_JK2, b, nCores = NaN, verbose = TRUE), regexp = "nCores must be an integer > 0.")
expect_error(compute_optimal_encoding(d_JK2, b, nCores = 1, verbose = 2), regexp = "verbose must be either TRUE or FALSE.")
})
test_that("compute_optimal_encoding works", {
set.seed(42)
n <- 200
Tmax <- 1
K <- 2
m <- 10
d <- generate_2State(n)
dT <- cut_data(d, Tmax)
row.names(dT) <- NULL
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 4)
expect_silent(fmca <- compute_optimal_encoding(dT, b, computeCI = FALSE, method = "parallel", nCores = 1, verbose = FALSE))
expect_type(fmca, "list")
expect_named(fmca, c("eigenvalues", "alpha", "pc", "F", "G", "V", "basisobj", "label", "pt", "runTime"))
# eigenvalues
expect_length(fmca$eigenvalues, K * m)
trueEigVal <- 1 / ((1:m) * (2:(m + 1)))
expect_lte(max(abs(fmca$eigenvalues[1:m] - trueEigVal)), 0.01)
# alpha
expect_type(fmca$alpha, "list")
expect_length(fmca$alpha, m * K)
expect_equal(dim(fmca$alpha[[1]]), c(m, K))
# pc
expect_equal(dim(fmca$pc), c(n, m * K))
# F
expect_equal(dim(fmca$F), c(m * K, m * K))
# G
expect_equal(dim(fmca$G), c(m * K, m * K))
# V
expect_equal(dim(fmca$V), c(n, m * K))
# basisobj
expect_equal(fmca$basisobj, b)
# label
expect_equal(fmca$label, data.frame(label = 0:1, code = 1:2))
})
skip_on_cran()
## data and results used in the next tests
set.seed(42)
n <- 10
Tmax <- 1
K <- 2
m <- 5
d <- generate_2State(n)
dT <- cut_data(d, Tmax)
row.names(dT) <- NULL
b <- create.bspline.basis(c(0, Tmax), nbasis = m, norder = 4)
fmca <- compute_optimal_encoding(dT, b, method = "parallel", nCores = 1, computeCI = FALSE, verbose = FALSE)
##
test_that("summary.cfda does not produce warnings/errors", {
expect_warning(summary(fmca), regexp = NA)
expect_error(summary(fmca), regexp = NA)
})
test_that("print.cfda does not produce warnings/errors", {
expect_warning(print(fmca), regexp = NA)
expect_error(print(fmca), regexp = NA)
})
test_that("compute_optimal_encoding works with tibble", {
skip_on_cran()
expect_silent(encoding <- compute_optimal_encoding(
tibble(dT[dT$id <= 10, ]), b,
computeCI = FALSE, nCores = 1, verbose = FALSE
))
})
test_that("compute_optimal_encoding works verbose", {
skip_on_cran()
expect_output(encoding <- compute_optimal_encoding(dT[dT$id <= 10, ], b, computeCI = FALSE, nCores = 1, verbose = TRUE))
})
test_that("compute_optimal_encoding throws a warning when the basis is not well suited", {
skip_on_cran()
data_msm <- data.frame(id = rep(1:2, each = 3), time = c(0, 3, 5, 0, 4, 5), state = c(1, 2, 2, 1, 2, 2))
b <- create.bspline.basis(c(0, 5), nbasis = 3, norder = 2)
expect_warning(
{
fmca <- compute_optimal_encoding(data_msm, b, computeCI = FALSE, nCores = 1)
},
regexp = paste(
"The F matrix contains at least one column of 0s.",
"At least one state is not present in the support of one basis function.",
"Corresponding coefficients in the alpha output will have a 0 value."
),
fixed = TRUE
)
})
test_that("get_encoding throws error", {
fmca <- list(alpha = rep(1, 5))
class(fmca) <- "fmca"
expect_error(get_encoding(3), regexp = "x must be a fmca object.")
expect_error(get_encoding(fmca, harm = c(1, 2)), regexp = "harm must be an integer between 1 and the number of components.")
expect_error(get_encoding(fmca, harm = 2.5), regexp = "harm must be an integer between 1 and the number of components.")
expect_error(get_encoding(fmca, harm = 0), regexp = "harm must be an integer between 1 and the number of components.")
expect_error(get_encoding(fmca, harm = NA), regexp = "harm must be an integer between 1 and the number of components.")
expect_error(get_encoding(fmca, harm = NaN), regexp = "harm must be an integer between 1 and the number of components.")
expect_error(get_encoding(fmca, harm = 10), regexp = "harm must be an integer between 1 and the number of components.")
expect_error(get_encoding(fmca, harm = 1, nx = 0), regexp = "nx must be an integer > 0.")
expect_error(get_encoding(fmca, harm = 1, nx = c(3, 2)), regexp = "nx must be an integer > 0.")
expect_error(get_encoding(fmca, harm = 1, nx = NA), regexp = "nx must be an integer > 0.")
expect_error(get_encoding(fmca, harm = 1, nx = NaN), regexp = "nx must be an integer > 0.")
})
test_that("get_encoding works", {
out <- get_encoding(fmca, fdObject = TRUE)
expect_s3_class(out, "fd")
out <- get_encoding(fmca, harm = 3, fdObject = TRUE)
expect_s3_class(out, "fd")
out <- get_encoding(fmca, fdObject = FALSE)
expect_named(out, c("x", "y"))
expect_equal(dim(out$y), c(128, 2))
expect_length(out$x, 128)
out <- get_encoding(fmca, harm = 3, fdObject = FALSE)
expect_named(out, c("x", "y"))
expect_equal(dim(out$y), c(128, 2))
expect_length(out$x, 128)
out <- get_encoding(fmca, fdObject = FALSE, nx = 100)
expect_named(out, c("x", "y"))
expect_equal(dim(out$y), c(100, 2))
expect_length(out$x, 100)
})
test_that("plot.fmca does not produce warnings", {
expect_warning(plot(fmca), regexp = NA)
expect_warning(plot(fmca, harm = 3, col = c("red", "blue")), regexp = NA)
expect_warning(plot(fmca, addCI = TRUE), regexp = NA)
})
test_that("plotComponent throws error", {
fmca <- list(pc = matrix(nrow = 3, ncol = 5))
class(fmca) <- "fmca"
expect_error(plotComponent(3), regexp = "x must be a fmca object.")
expect_error(plotComponent(fmca, comp = 1), regexp = "comp must be a vector of positive integers of length 2.")
expect_error(plotComponent(fmca, comp = c(1, NA)), regexp = "comp must be a vector of positive integers of length 2.")
expect_error(plotComponent(fmca, comp = c(1, NaN)), regexp = "comp must be a vector of positive integers of length 2.")
expect_error(plotComponent(fmca, comp = c(1, 1.5)), regexp = "comp must be a vector of positive integers of length 2.")
expect_error(plotComponent(fmca, comp = c(1, 6)), regexp = "comp must be a vector of positive integers of length 2.")
})
test_that("plotComponent does not produce warnings", {
expect_warning(plotComponent(fmca, addNames = TRUE), regexp = NA)
expect_warning(plotComponent(fmca, comp = c(2, 3), addNames = FALSE), regexp = NA)
expect_warning(plotComponent(fmca, shape = 23), regexp = NA)
})
test_that("plotEigenvalues throws error", {
expect_error(plotEigenvalues(2), regexp = "x must be a fmca object.")
})
test_that("plotEigenvalues does not produce warnings", {
expect_warning(plotEigenvalues(fmca, cumulative = FALSE, normalize = FALSE), regexp = NA)
expect_warning(plotEigenvalues(fmca, cumulative = FALSE, normalize = TRUE), regexp = NA)
expect_warning(plotEigenvalues(fmca, cumulative = TRUE, normalize = FALSE), regexp = NA)
expect_warning(plotEigenvalues(fmca, cumulative = TRUE, normalize = TRUE, shape = 23), regexp = NA)
})
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.