View source: R/longitudinal_grmtree.R
| longitudinal_grmtree | R Documentation |
This function implements a tree-based longitudinal graded response model
using model-based recursive partitioning (MOB) to detect measurement
heterogeneity in patient-reported outcome measures (PROMs) measured at two
time points. The Longitudinal GRMTree extends the cross-sectional
grmtree to the longitudinal setting by embedding a
constrained two-factor GRM within the MOB framework. The resulting tree
identifies patient subgroups where the longitudinal measurement model
differs, providing the foundation for subgroup-specific response shift
characterization via rs_characterize.
longitudinal_grmtree(
formula,
data,
n_items = NULL,
na.action = na.omit,
control = grmtree.control(),
mtry = NULL,
...
)
formula |
A formula specifying the model structure with a wide-format
response matrix on the left-hand side and partitioning variables on the
right-hand side (e.g., |
data |
A data frame containing the variables in the formula. Must
include the response matrix as a matrix-valued column (created via
|
n_items |
Integer specifying the number of items per time point. If
|
na.action |
How to handle missing values. Default is |
control |
A list of control parameters created by
|
mtry |
Number of variables randomly sampled as candidates at each split.
If |
... |
Additional arguments passed to the internal fitting function
|
The Longitudinal GRMTree is a unified framework for response shift detection that operates in two phases:
Phase 1 (this function): Identifies patient subgroups where the constrained longitudinal measurement model differs. The constrained model represents the null hypothesis of no response shift (item parameters equal across time). MOB tests whether this null model's item parameters are stable across patient covariates and recursively partitions the sample where instability is detected.
Phase 2 (rs_characterize): Within each terminal node,
tests whether item parameters actually change from T1 to T2 by comparing the
constrained model to an unconstrained model using likelihood ratio tests.
This phase characterizes response shift at the item level, classifying
changes as recalibration, reprioritization, or both.
Let Y_{im} denote the response of individual i to item m at
time t. The longitudinal GRM specifies two correlated latent factors:
\theta_{i,T1} \sim N(0, 1)
\theta_{i,T2} \sim N(\mu_{T2},
\sigma^2_{T2})
Cov(\theta_{i,T1}, \theta_{i,T2}) = \sigma_{12}
For item m at time t, the graded response model is:
P(Y_{im,t} \geq j | \theta_{i,t}) = \frac{\exp(a_{m,t}(\theta_{i,t}
- b_{mj,t}))}{1 + \exp(a_{m,t}(\theta_{i,t} - b_{mj,t}))}
where a_{m,t} is the discrimination parameter and b_{mj,t} are
threshold parameters for item m at time t.
Under the no-response-shift constraint:
a_{m,T1} = a_{m,T2} \quad \text{and} \quad b_{mj,T1} = b_{mj,T2}
\quad \forall m, j
This means item parameters are identical across time, so any observed
changes in responses are attributed to true latent change (\mu_{T2})
rather than changes in measurement properties.
Step 1: Global Model Estimation. Fit the constrained longitudinal
GRM to all individuals at the root node, estimating item parameters
\hat{\beta} and latent parameters (\mu_{T2}, \sigma^2_{T2},
\sigma_{12}) via maximum likelihood.
Step 2: Parameter Stability Testing. For each covariate
X_p, compute individual score function contributions
s(\hat{\beta}; \mathbf{y}_i) and test whether the item-parameter
scores fluctuate systematically with X_p using structural change
tests; the structural-parameter scores (the follow-up mean \mu_{T2}
and the between-occasion covariance \sigma_{12}) are held out, so the
null hypothesis is that the item parameters are stable across all values of
X_p.
Step 3: Recursive Partitioning. If significant instability is detected (after p-value adjustment):
Select the covariate X_p^* with strongest instability
Find the optimal split point c^* maximizing the partitioned
log-likelihood
Split the sample: X_p^* \leq c^* vs. X_p^* > c^*
Step 4: Recursion. Repeat Steps 1–3 within each child node until no significant instability remains or the minimum node size is reached.
Step 5 (Post-hoc): Apply rs_characterize to test
for response shift within each terminal node.
The fitted Longitudinal GRMTree provides a piecewise constrained longitudinal GRM:
P(Y_{im,t} = k | \theta_{i,t}, \mathbf{x}_i) = \sum_{b=1}^B
I(\mathbf{x}_i \in \mathcal{X}_b) \cdot P_b(Y_{im,t} = k | \theta_{i,t})
where B is the number of terminal nodes, \mathcal{X}_b is
the covariate subspace defining terminal node b, and P_b is
the node-specific constrained longitudinal GRM. Each terminal node
contains:
Node-specific constrained item parameters (equal across T1 and T2)
Node-specific latent trait parameters: \mu_{T2,b},
\sigma^2_{T2,b}, r_{T1,T2,b}
The tree structure identifies patient subgroups whose item parameters differ, i.e. subgroups with differential item functioning in the constrained longitudinal measurement model. A split reflects:
Different item discrimination patterns across subgroups
Different threshold locations across subgroups
The structural parameters – the true latent change \mu_{T2},
the follow-up latent variance \sigma^2_{T2}, and the
test-retest correlation – are estimated and reported at every node but are
held out of the split test, so a subgroup difference in how much the
construct truly changed, or in its stability over time, cannot by itself
produce a split.
Crucially, the tree does not directly detect response shift
(temporal change in item parameters within a subgroup). Response shift
is tested in Phase 2 using rs_characterize, which relaxes
the equality constraints within each terminal node. A tree with only one
terminal node (no split) indicates that no covariate moderates the
measurement model; it does not imply the absence of response
shift, since rs_characterize can still detect uniform RS in
the unsplit root node.
The Longitudinal GRMTree extends several existing approaches:
GRMTree (Arimoro et al., 2026): Cross-sectional DIF detection using tree-based GRM. The longitudinal extension embeds a two-factor model instead of a single-factor model.
LIRTree (Ames & Leventhal, 2021): Longitudinal tree-based IRT using Rasch/2PL models. The GRM extension allows item-specific discrimination parameters, which are important for PROMs where items vary in discriminating ability.
Oort SEM (Oort, 2005): Response shift detection via structural equation modeling. The tree-based approach removes the requirement for pre-specified subgroups.
Minimum node size: Use at least 10–25 times the number
of free parameters per node. For M items with K response
categories, the constrained model has approximately M(K-1) + M + 3
parameters (M discriminations, M(K-1) thresholds, and 3
latent parameters). For 8 items with 5 categories:
8 \times 4 + 8 + 3 = 43 parameters, suggesting
minbucket = 200--400.
Number of covariates: Bonferroni correction becomes
increasingly conservative with more covariates. Consider using
p_adjust = "BH" for exploratory analyses with many covariates.
Sample size: With typical PROM instruments (5–15 items), a total sample of at least 500–1000 is recommended for adequate power to detect meaningful splits.
Response matrix preparation: Use
prepare_longitudinal_data to construct the wide-format
response matrix from separate T1 and T2 item columns.
An object of class c("longitudinal_grmtree", "grmtree",
"modelparty", "party") containing the fitted tree structure. The object
inherits from modelparty and includes:
Accessible via standard partykit methods
such as nodeids,
data_party, and indexing with [[.
Each terminal node contains a fitted constrained
longitudinal GRM with item parameters (discrimination and thresholds),
latent trait means (\mu_{T2}), and latent trait covariance
matrix (\sigma^2_{T2}, r_{T1,T2}).
info$n_itemsNumber of items per time point.
info$model_type"longitudinal_grm".
info$p_adjustThe p-value adjustment method used.
info$callThe original function call.
Olayinka Imisioluwa Arimoro olayinka.arimoro@ucalgary.ca, Lisa M. Lix, Tolulope T. Sajobi
Arimoro, O. I., Lix, L. M., Patten, S. B., Sawatzky, R., Sebille, V., Liu, J., Wiebe, S., Josephson, C. B., & Sajobi, T. T. (2025). Tree-based latent variable model for assessing differential item functioning in patient-reported outcome measures: a simulation study. Quality of Life Research. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s11136-025-04018-6")}
Ames, A. J., & Leventhal, B. C. (2021). Application of a longitudinal IRTree model: response style changes over time. Educational and Psychological Measurement, 81(3), 561–582.
Oort, F. J. (2005). Using structural equation modeling to detect response shifts and true change. Quality of Life Research, 14(3), 587–598.
Samejima, F. (1969). Estimation of latent ability using a response pattern of graded scores. Psychometrika Monograph Supplement, 34, 100–114.
Sprangers, M. A., & Schwartz, C. E. (1999). Integrating response shift into health-related quality of life research. Social Science & Medicine, 48(11), 1507–1515.
Zeileis, A., Hothorn, T., & Hornik, K. (2008). Model-based recursive partitioning. Journal of Computational and Graphical Statistics, 17(2), 492–514.
rs_characterize for Phase 2 response shift characterization,
prepare_longitudinal_data for data preparation,
grmtree for cross-sectional DIF detection,
grmtree.control for control parameters,
mob for the underlying MOB framework
library(grmtree)
# Load the synthetic longitudinal data
data("grmtree_long_data", package = "grmtree")
# Prepare the wide-format response matrix
items_t1 <- c("MOS_Listen", "MOS_Info", "MOS_Advice_Crisis", "MOS_Confide",
"MOS_Advice_Want", "MOS_Fears", "MOS_Personal", "MOS_Understand")
ld <- prepare_longitudinal_data(
data = grmtree_long_data,
items_t1 = items_t1,
items_t2 = paste0(items_t1, "_year1"),
covariates = c("sex", "age", "residency", "job",
"education", "comorbidity_count", "ever_smoker")
)
# Phase 1: fit the longitudinal GRM tree
ltree <- longitudinal_grmtree(
resp_wide ~ sex + age + residency + job +
education + comorbidity_count + ever_smoker,
data = ld, n_items = 8,
control = grmtree.control(minbucket = 200)
)
# Print tree structure
print(ltree)
# Plot threshold regions
plot(ltree, type = "regions", tnex = 2L)
# Phase 2: characterize response shift within each subgroup
rs <- rs_characterize(ltree, p_adjust = "fdr",
global_p_adjust = "bonferroni")
print(rs)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.