The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
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)
#> Correlation summary
#> output : matrix
#> dimensions : 3 x 3
#> retained_pairs: 3
#> threshold : 0.0000
#> diag : included
#> estimate : -0.3995 to 0.9397
#>
#> item1 item2 estimate n
#> x y 0.9397 56
#> y z -0.3995 56
#> x z -0.3843 56Agreement 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)
#>
#> Bland-Altman (two methods) (95% CI)
#>
#> Agreement estimates
#>
#> n_obs bias sd_loa loa_low loa_up width
#> 56 0.654 0.651 -0.622 1.93 2.552
#>
#> Confidence intervals
#>
#> bias_lwr bias_upr lo_lwr lo_upr up_lwr up_upr
#> 0.483 0.824 -0.793 -0.452 1.759 2.101
#>
#> Model details
#>
#> sigma2_subject sigma2_resid residual_model
#> 0 0.424 iidThe 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)
#> Lin's concordance summary
#> method : Repeated-measures Lin's concordance
#> dimensions : 2 x 2
#> pairs : 1
#> estimate : 0.7180
#> most_negative: A-B (0.7180)
#> most_positive: A-B (0.7180)
#>
#> item1 item2 estimate
#> A B 0.7180
summary(fit_ccc_reml)
#>
#> Repeated-measures concordance (REML)
#>
#> Concordance estimates
#>
#> item1 item2 estimate n_subjects n_obs SB se_ccc
#> A B 0.5391 14 112 0.4093 0.0824
#>
#> Variance components
#>
#> sigma2_subject sigma2_subject_method sigma2_subject_time sigma2_error
#> 0.4785 0.0997 0.5943 0.1085
#>
#> AR(1) diagnostics
#>
#> ar1_rho ar1_rho_lag1 ar1_rho_mom ar1_pairs ar1_pval use_ar1 ar1_recommend
#> -0.3941 -0.3941 -0.3941 84 3e-04 FALSE FALSEThe 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)
#>
#> Repeated-measures intraclass correlation (REML) (95% CI)
#>
#> ICC estimates
#>
#> item1 item2 estimate lwr upr n_subjects n_obs se_icc residual_model
#> A B 0.6347 0.63 0.64 14 112 0.0022 iid
#>
#> Variance components
#>
#> sigma2_subject sigma2_subject_method sigma2_subject_time sigma2_error SB
#> 0.4785 0.0997 0.5943 0.1085 0.4093
#>
#> AR(1) diagnostics
#>
#> ar1_rho_lag1 ar1_rho_mom ar1_pairs ar1_pval use_ar1 ar1_recommend
#> -0.3941 -0.3941 84 3e-04 FALSE FALSE
summary(fit_icc_agr)
#>
#> Repeated-measures intraclass correlation (REML)
#>
#> ICC estimates
#>
#> item1 item2 estimate n_subjects n_obs se_icc residual_model
#> A B 0.4113 14 112 0.0629 iid
#>
#> Variance components
#>
#> sigma2_subject sigma2_subject_method sigma2_subject_time sigma2_error SB
#> 0.4785 0.0997 0.5943 0.1085 0.4093
#>
#> AR(1) diagnostics
#>
#> ar1_rho_lag1 ar1_rho_mom ar1_pairs ar1_pval use_ar1 ar1_recommend
#> -0.3941 -0.3941 84 3e-04 FALSE FALSE
estimate(fit_icc_cons)
#> A B
#> A 1.0000000 0.6346672
#> B 0.6346672 1.0000000
confint(fit_icc_cons)
#> item1 item2 lwr upr
#> 1 A B 0.6304005 0.6389129
ci(fit_icc_cons)
#> $lwr
#> A B
#> A NA 0.6304005
#> B 0.6304005 NA
#>
#> $upr
#> A B
#> A NA 0.6389129
#> B 0.6389129 NA
#>
#> $conf.level
#> [1] 0.95
#>
#> $ci.method
#> NULL
tidy(fit_icc_cons)
#> item1 item2 estimate lwr upr
#> row A B 0.6346672 0.6304005 0.6389129The 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]
)
)
#> method estimate
#> 1 Repeated CCC (REML) 0.5390697
#> 2 Repeated ICC (agreement, REML) 0.4113387The 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.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.