Nothing
grid <- round(seq(0, 10, length.out = 11), 3)
# use (0.1 * grid + 1) so curves don't all coincide at t=0,
# avoiding platform-dependent tie-breaking in depth computations
lin <- -3:3 * tfd(0.1 * grid + 1, grid)
parallel <- -3:3 + tfd(0 * grid, grid)
names(lin) <- names(parallel) <- 1:7
spike_regular <- c(parallel, tfd(100 * (grid == 10), grid))
spike_irregular <- c(
-3:3 + tfd(c(0 * grid, 0), c(grid, 20)),
tfd(100 * (c(grid, 20) == 20), c(grid, 20))
)
na <- 1 * NA + lin[1]
lin_irreg <- {
m <- as.matrix(lin)
m[cbind(2:7, 2:7)] <- NA
tfd(m, evaluator = tf_approx_linear)
}
lin_b <- tfb(lin, verbose = FALSE) |> suppressWarnings()
test_that("MBD works", {
ranks <- c(1.5, 3.5, 5.5, 7, 5.5, 3.5, 1.5)
names(ranks) <- names(lin)
expect_equal(rank(tf_depth(lin, depth = "MBD")), ranks)
expect_equal(rank(tf_depth(parallel, depth = "MBD")), ranks)
expect_equal(rank(tf_depth(lin_irreg, depth = "MBD")), ranks)
expect_equal(rank(tf_depth(lin_b, depth = "MBD")), ranks)
# weighting by interval length:
# increases importance of last point -> lower depth
expect_gt(
tail(tf_depth(spike_regular), 1),
tail(tf_depth(spike_irregular), 1)
)
})
test_that("FM works", {
# FM should give central curve the highest depth (1 = most central)
expect_equal(which.max(tf_depth(lin, depth = "FM")), c("4" = 4))
expect_equal(which.max(tf_depth(parallel, depth = "FM")), c("4" = 4))
# FM works with irregular and basis representations
expect_equal(which.max(tf_depth(lin_irreg, depth = "FM")), c("4" = 4))
expect_equal(which.max(tf_depth(lin_b, depth = "FM")), c("4" = 4))
# FM values in [0, 1]
fm_vals <- tf_depth(lin, depth = "FM")
expect_true(all(fm_vals >= 0 & fm_vals <= 1))
# FM ranking: central curve deepest for parallel data
expect_equal(which.max(tf_depth(parallel, depth = "FM")), c("4" = 4))
# weighting by interval length
expect_gt(
tail(tf_depth(spike_regular, depth = "FM"), 1),
tail(tf_depth(spike_irregular, depth = "FM"), 1)
)
})
test_that("FM handles ties consistently", {
identical_curves <- matrix(c(1, 1, 1, 1, 1, 1), nrow = 3, byrow = TRUE)
expect_equal(tf_depth(identical_curves, depth = "FM"), c(0, 0, 0))
tied_curves <- matrix(c(0, 0, 0, 0, 1, 1), nrow = 3, byrow = TRUE)
expect_equal(tf_depth(tied_curves, depth = "FM"), c(2 / 3, 2 / 3, 0))
expect_equal(
tf_depth(tied_curves[c(3, 1, 2), , drop = FALSE], depth = "FM"),
c(0, 2 / 3, 2 / 3)
)
})
test_that("FSD works", {
# FSD gives symmetric depths for parallel lines (within floating-point tolerance)
fsd_par <- unname(tf_depth(parallel, depth = "FSD"))
expect_equal(fsd_par[1], fsd_par[7], tolerance = 1e-10)
expect_equal(fsd_par[2], fsd_par[6], tolerance = 1e-10)
expect_equal(fsd_par[3], fsd_par[5], tolerance = 1e-10)
expect_gt(fsd_par[4], fsd_par[3])
# central curve has highest depth (1 = most central)
expect_equal(which.max(tf_depth(lin, depth = "FSD")), c("4" = 4))
expect_equal(which.max(tf_depth(parallel, depth = "FSD")), c("4" = 4))
# works with irregular and basis representations
expect_equal(which.max(tf_depth(lin_irreg, depth = "FSD")), c("4" = 4))
expect_equal(which.max(tf_depth(lin_b, depth = "FSD")), c("4" = 4))
# FSD values in [0, 1]
fsd_vals <- tf_depth(lin, depth = "FSD")
expect_true(all(fsd_vals >= 0 & fsd_vals <= 1))
# weighting by interval length
expect_gt(
tail(tf_depth(spike_regular, depth = "FSD"), 1),
tail(tf_depth(spike_irregular, depth = "FSD"), 1)
)
})
test_that("RPD works", {
withr::local_seed(4217)
# central curve has highest depth (1 = most central)
expect_equal(which.max(tf_depth(lin, depth = "RPD")), c("4" = 4))
# central curve deepest for parallel lines
expect_equal(which.max(tf_depth(parallel, depth = "RPD")), c("4" = 4))
# RPD values in (0, 1]
rpd_vals <- tf_depth(lin, depth = "RPD")
expect_true(all(rpd_vals > 0 & rpd_vals <= 1))
# works with irregular and basis representations
expect_equal(which.max(tf_depth(lin_irreg, depth = "RPD")), c("4" = 4))
expect_equal(which.max(tf_depth(lin_b, depth = "RPD")), c("4" = 4))
# RPD detects shape outliers that MBD misses:
skip_on_cran()
set.seed(42)
t_grid <- seq(0, 1, length.out = 101)
n_curves <- 50
normal_mat <- matrix(0, n_curves, length(t_grid))
for (i in seq_len(n_curves)) {
normal_mat[i, ] <- cumsum(rnorm(length(t_grid), sd = 0.1))
}
outlier_mat <- matrix(sin(20 * pi * t_grid) * 0.5, nrow = 1)
all_curves <- tfd(rbind(normal_mat, outlier_mat), arg = t_grid)
rpd_depths <- tf_depth(
all_curves,
depth = "RPD",
n_projections = 10000L,
n_projections_beta = 1000L
)
mbd_depths <- tf_depth(all_curves, depth = "MBD")
# RPD should rank the shape outlier lower (less central) than MBD does
expect_lt(rank(rpd_depths)[n_curves + 1], rank(mbd_depths)[n_curves + 1])
})
test_that("matrix na.rm drops incomplete observations", {
x <- matrix(c(0, NA, 1, 1, 2, 2), nrow = 3, byrow = TRUE)
expect_equal(tf_depth(x, depth = "FM", na.rm = TRUE), c(1, 0))
expect_equal(tf_depth(x, depth = "FSD", na.rm = TRUE), c(0.5, 0.5))
withr::local_seed(4217)
expect_equal(
tf_depth(
x,
depth = "RPD",
na.rm = TRUE,
n_projections = 100L,
n_projections_beta = 20L
),
c(0.5, 0.5)
)
})
test_that("median works", {
expect_true(is.na(median(c(na, lin))))
expect_identical(median(c(na, lin), na.rm = TRUE), median(lin))
expect_message(median(lin[1:2]), "maximal depth")
})
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.