knitr::opts_chunk$set( collapse = TRUE, comment = "#>", warning = FALSE, message = FALSE )
Repeated-measures analysis requires a different data layout and, usually, a different estimand. The wide-data matrix workflow is not enough because the analysis must account for the repeated structure within subject.
This vignette covers:
rmcorr()ba_rm()ccc_rm_ustat()ccc_rm_reml()icc_rm_reml()Repeated-measures functions use a subject argument for the subject identifier
role, including rmcorr(), ba_rm(), ccc_rm_ustat(), ccc_rm_reml(), and
icc_rm_reml().
library(matrixCorr) set.seed(50) n_id <- 14 n_time <- 4 dat <- expand.grid( id = factor(seq_len(n_id)), time = factor(seq_len(n_time)), method = factor(c("A", "B")) ) dat$time_index <- as.integer(dat$time) subj <- rnorm(n_id, sd = 1.0)[dat$id] subject_method <- rnorm(n_id * 2, sd = 0.25) sm <- subject_method[(as.integer(dat$id) - 1L) * 2L + as.integer(dat$method)] subject_time <- rnorm(n_id * n_time, sd = 0.75) st <- subject_time[(as.integer(dat$id) - 1L) * n_time + as.integer(dat$time)] dat$y <- subj + sm + st + 0.35 * (dat$method == "B") + rnorm(nrow(dat), sd = 0.35)
rmcorr() targets within-subject association, not agreement. It is the right
function when the question is whether two responses vary together within
subjects after removing subject-level offsets.
set.seed(51) dat_rmcorr <- data.frame( id = rep(seq_len(n_id), each = n_time), x = rnorm(n_id * n_time), y = rnorm(n_id * n_time), z = rnorm(n_id * n_time) ) dat_rmcorr$y <- 0.7 * dat_rmcorr$x + rnorm(n_id, sd = 1)[dat_rmcorr$id] + rnorm(nrow(dat_rmcorr), sd = 0.3) fit_rmcorr <- rmcorr(dat_rmcorr, response = c("x", "y", "z"), subject = "id") summary(fit_rmcorr)
Agreement methods require method labels and, for paired repeated analysis, a time or replicate key.
ba_rm() is the repeated-measures Bland-Altman route. It models subject-time
matched paired differences and returns bias and limits of agreement.
fit_ba_rm <- ba_rm( dat, response = "y", subject = "id", method = "method", time = "time_index" ) summary(fit_ba_rm)
The package provides two repeated-measures CCC routes.
ccc_rm_ustat() is a nonparametric U-statistic approach.ccc_rm_reml() uses the REML mixed-model backend.fit_ccc_ustat <- ccc_rm_ustat( dat, response = "y", subject = "id", method = "method", time = "time_index" ) fit_ccc_reml <- ccc_rm_reml( dat, response = "y", subject = "id", method = "method", time = "time_index", ci = FALSE ) summary(fit_ccc_ustat) summary(fit_ccc_reml)
The two functions are related, but they are not interchangeable. The U-statistic route is useful when its design assumptions are appropriate. The REML route is the more flexible model-based path when variance components and residual structure need to be handled explicitly.
icc_rm_reml() uses the same REML and Woodbury backend as repeated CCC, but it
targets a different reliability quantity.
fit_icc_cons <- icc_rm_reml( dat, response = "y", subject = "id", method = "method", time = "time_index", type = "consistency", ci = TRUE ) fit_icc_agr <- icc_rm_reml( dat, response = "y", subject = "id", method = "method", time = "time_index", type = "agreement", ci = FALSE ) summary(fit_icc_cons) summary(fit_icc_agr)
The simulation above gives the subject-time component a visibly non-trivial variance contribution. That makes the CCC-versus-ICC distinction easier to see:
data.frame( method = c("Repeated CCC (REML)", "Repeated ICC (agreement, REML)"), estimate = c( fit_ccc_reml[1, 2], fit_icc_agr[1, 2] ) )
The most important distinction between repeated CCC and repeated ICC is the numerator. Repeated ICC uses only the stable between-subject variance in the numerator. Repeated CCC also credits the time-averaged subject-time component. As a result, the two summaries can differ materially even when they are fitted through the same backend.
The method choice should follow the scientific question.
rmcorr() for within-subject association.ba_rm() for repeated-measures bias and limits of agreement.ccc_rm_ustat() or ccc_rm_reml() for repeated concordance.icc_rm_reml() for repeated reliability under a variance-components
interpretation.The shared long-format interface is intentional. The statistical targets are different, but the package keeps the surrounding workflow stable.
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.