Learn R Programming

matrixCorr (version 0.12.3)

rmcorr: Repeated-Measures Correlation (rmcorr)

Description

Computes repeated-measures correlation for two or more continuous responses observed repeatedly within subjects. Supply a data.frame plus column names, or pass the response matrix/data frame and subject vector directly. The repeated observations are indexed only by subject, thus no explicit time variable is modeled, and the method targets a common within-subject linear association after removing subject-specific means.

Usage

rmcorr(
  data = NULL,
  response,
  subject,
  na_method = c("error", "pairwise", "complete"),
  conf_level = 0.95,
  n_threads = getOption("matrixCorr.threads", 1L),
  keep_data = FALSE,
  verbose = FALSE,
  estimator = c("ancova", "weighted"),
  ci_method = c("auto", "fisher_z", "bootstrap", "none"),
  n_boot = 999L,
  seed = NULL,
  ...
)

rmcorr_weighted(data = NULL, response, subject, ...)

Value

Either a "rmcorr" object (exactly two responses) or a "rmcorr_matrix" object (pairwise results when \(\ge\)3 responses).

If "rmcorr" (exactly two responses), outputs include:

  • estimate; repeated-measures correlation estimate.

  • p_value; two-sided p-value for the common within-subject slope.

  • lwr, upr; confidence interval limits for estimate.

  • slope; common within-subject slope.

  • df; residual degrees of freedom \(N - S - 1\).

  • n_obs; number of complete observations retained after dropping subjects with fewer than two repeated pairs.

  • n_subjects; number of contributing subjects.

  • responses; names of the fitted response variables.

  • compatibility aliases r, conf_int, and based.on are reconstructed on access without duplicate storage.

  • when keep_data = TRUE, compact source data are retained so plot() can lazily reconstruct data_long, intercepts, and fitted lines; these are otherwise not stored.

If "rmcorr_matrix" (\(\ge\)3 responses), outputs are:

  • a symmetric numeric matrix of pairwise repeated-measures correlations.

  • attributes method, description, and package = "matrixCorr".

  • diagnostics; a list with square matrices for slope, p_value, df, n_complete, n_subjects, conf_low, and conf_high, plus scalar conf_level.

Arguments

data

Optional data.frame/matrix containing the repeated-measures dataset.

response

Either:

  • a character vector of at least two column names in data, or

  • a numeric matrix/data frame with at least two columns.

If exactly two responses are supplied, the function returns a pairwise repeated-measures correlation object of class "rmcorr". If three or more responses are supplied, a symmetric matrix of class "rmcorr_matrix" is returned.

subject

Subject identifier (factor/character/integer/numeric) or a single character string naming the subject column in data.

na_method

Character scalar controlling missing-data handling. "error" rejects missing values in the selected response columns or subject. "pairwise" uses pairwise complete cases and drops subjects with fewer than two complete pairs for the specific contrast. "complete" removes rows with missing or non-finite values in subject and all selected response variables before fitting.

conf_level

Confidence level used for Wald confidence intervals on the repeated-measures correlation (default 0.95).

n_threads

Integer \(\ge 1\). Number of OpenMP threads used by the C++ backend in matrix mode. Defaults to getOption("matrixCorr.threads", 1L).

keep_data

Logical (default FALSE). If TRUE, returned objects retain a compact copy of the numeric response matrix plus encoded subject identifiers. For pairwise fits this enables plot() to reconstruct subject-level fitted lines lazily; for matrix outputs it also allows view_rmcorr_shiny() to rebuild pairwise scatterplots from the returned object alone.

verbose

Logical; if TRUE, prints a short note about the thread count used in matrix mode.

estimator

Character scalar selecting the repeated-measures correlation estimator. "ancova" (default) is the classical subject-centred repeated-measures correlation. "weighted" is the weighted repeated-measures correlation coefficient of Kondo et al. (2025), designed for incomplete or unbalanced repeated-measurement schedules.

ci_method

Confidence-interval engine. "auto" (default) resolves to "fisher_z" for estimator = "ancova" and to subject-level "bootstrap" for estimator = "weighted" when n_boot > 0; otherwise "none". "none" returns NA bounds.

n_boot

Integer \(\ge 0\). Number of subject-level bootstrap resamples when ci_method = "bootstrap".

seed

Optional positive integer seed used for bootstrap reproducibility.

...

Deprecated compatibility aliases. The legacy check_na argument is still accepted here temporarily.

Author

Thiago de Paula Oliveira

Details

Repeated-measures correlation estimates the common within-subject linear association between two variables measured repeatedly on the same subjects. It differs from agreement methods such as Lin's CCC or Bland-Altman analysis because those target concordance or interchangeability, whereas repeated-measures correlation targets the strength of the subject-centred association.

For subject \(i = 1,\ldots,S\) and repeated observations \(j = 1,\ldots,n_i\), let \(x_{ij}\) and \(y_{ij}\) denote the two responses. Define subject-specific means $$\bar x_i = \frac{1}{n_i}\sum_{j=1}^{n_i} x_{ij}, \qquad \bar y_i = \frac{1}{n_i}\sum_{j=1}^{n_i} y_{ij}.$$ The repeated-measures correlation uses within-subject centred values $$x^\ast_{ij} = x_{ij} - \bar x_i, \qquad y^\ast_{ij} = y_{ij} - \bar y_i$$ and computes $$r_{\mathrm{rm}} = \frac{\sum_i \sum_j x^\ast_{ij} y^\ast_{ij}} {\sqrt{\left(\sum_i \sum_j {x^\ast_{ij}}^2\right) \left(\sum_i \sum_j {y^\ast_{ij}}^2\right)}}.$$

Equivalently, this is the correlation implied by an ANCOVA model with a common slope and subject-specific intercepts: $$y_{ij} = \alpha_i + \beta x_{ij} + \varepsilon_{ij}.$$ The returned slope is $$\hat\beta = \frac{\sum_i \sum_j x^\ast_{ij} y^\ast_{ij}} {\sum_i \sum_j {x^\ast_{ij}}^2},$$ and the subject-specific fitted intercepts are \(\hat\alpha_i = \bar y_i - \hat\beta \bar x_i\). Residual degrees of freedom are \(N - S - 1\), where \(N = \sum_i n_i\) after filtering to complete observations and retaining only subjects with at least two repeated pairs.

Confidence intervals are computed with a Fisher \(z\)-transformation of \(r_{\mathrm{rm}}\) and then back-transformed to the correlation scale. In matrix mode, the same estimator is applied to every pair of selected response columns.

With estimator = "weighted", the package implements the weighted repeated-measures estimator from Kondo et al. (2025) using complete observed \((x,y)\) pairs per contrast. This estimator does not impute missing data; it uses per-subject complete-pair sets and weighted sums of explained and residual quantities from the fixed-subject ANCOVA decomposition.

Bootstrap confidence intervals use non-parametric subject-level resampling (subjects are resampled as blocks, not rows).

References

Bakdash, J. Z., & Marusich, L. R. (2017). Repeated Measures Correlation. Frontiers in Psychology, 8, 456. tools:::Rd_expr_doi("10.3389/fpsyg.2017.00456")

Kondo, M., Nagashima, K., Isono, S., & Sato, Y. (2025). Weighted Repeated Measures Correlation Coefficient: A New Correlation Coefficient for Handling Missing Data With Repeated Measures. Statistics in Medicine, 44(10-12), e70046. tools:::Rd_expr_doi("10.1002/sim.70046")

Examples

Run this code
set.seed(2026)
n_subjects <- 20
n_rep <- 4
subject <- rep(seq_len(n_subjects), each = n_rep)
subj_eff_x <- rnorm(n_subjects, sd = 1.5)
subj_eff_y <- rnorm(n_subjects, sd = 2.0)
within_signal <- rnorm(n_subjects * n_rep)

dat <- data.frame(
  subject = subject,
  x = subj_eff_x[subject] + within_signal + rnorm(n_subjects * n_rep, sd = 0.2),
  y = subj_eff_y[subject] + 0.8 * within_signal + rnorm(n_subjects * n_rep, sd = 0.3),
  z = subj_eff_y[subject] - 0.4 * within_signal + rnorm(n_subjects * n_rep, sd = 0.4)
)

fit_xy <- rmcorr(dat, response = c("x", "y"), subject = "subject", keep_data = TRUE)
print(fit_xy)
summary(fit_xy)
estimate(fit_xy)
tidy(fit_xy)
ci(fit_xy)
confint(fit_xy)
plot(fit_xy)

fit_mat <- rmcorr(dat, response = c("x", "y", "z"), subject = "subject")
print(fit_mat, digits = 3)
summary(fit_mat)
tidy(fit_mat)
plot(fit_mat)

if (interactive() && requireNamespace("shiny", quietly = TRUE)) {
  fit_mat_view <- rmcorr(
    dat,
    response = c("x", "y", "z"),
    subject = "subject",
    keep_data = TRUE
  )
  view_rmcorr_shiny(fit_mat_view)
}

Run the code above in your browser using DataLab