View source: R/rs_characterize.R
| rs_characterize | R Documentation |
After fitting a longitudinal_grmtree (Phase 1), this function
performs Phase 2: post-hoc response shift (RS) characterization within each
terminal node. For each subgroup identified by the tree it compares the
constrained model (no RS: item parameters equal across time) to an
unconstrained model (item parameters free across time) with a likelihood
ratio test (LRT); then, only in nodes where the omnibus test survives
the across-node adjustment, it tests each item for RS and classifies the
type of shift by nested LRTs on the item's parameter sets.
rs_characterize(
object,
node = NULL,
item_level = TRUE,
alpha = 0.05,
p_adjust = "bonferroni",
global_p_adjust = "bonferroni",
rs_threshold = 0.3,
verbose = TRUE,
...
)
object |
A |
node |
Optional integer vector of terminal node IDs to analyze. If
|
item_level |
Logical. If |
alpha |
Numeric significance level for RS tests. Default |
p_adjust |
Character string specifying the method for adjusting the
item detection p-values within each node. Controls the
error rate when testing multiple items for RS within a single subgroup.
Options: |
global_p_adjust |
Character string specifying the method for adjusting
the omnibus RS p-values across terminal nodes. Controls the
family-wise error rate when testing RS in multiple subgroups. Options are
the same as |
rs_threshold |
Numeric magnitude threshold on the IRT parameter scale,
used only for the descriptive effect-size annotation
( |
verbose |
Logical. If |
... |
Additional arguments passed to |
Phase 1 (longitudinal_grmtree) embeds a constrained
longitudinal GRM (item parameters equal across T1 and T2) in model-based
recursive partitioning, identifying subgroups that require different
constrained measurement models. Phase 2 (this function) relaxes the
equality constraints within each subgroup and asks whether item parameters
actually change over time. This separates between-group measurement
heterogeneity (captured by the tree) from within-group temporal change
(response shift).
For each terminal node, a constrained model (all item parameters equal across waves) and an unconstrained model (all free) are fitted and compared by
\chi^2 = -2(\ell_{con} - \ell_{uncon}), \qquad
\mathrm{df} = \#\{\text{freed constraints}\}.
The omnibus p-values are then adjusted across nodes
(global_p_adjust) and RS_detected is set from the adjusted
p-value. Item-level testing is performed only for nodes with
RS_detected == TRUE: a node that is not significant after adjustment is
skipped, so it contributes no item rows. This is a deliberate two-pass design
(all omnibus tests first, then adjustment, then item-level only where
warranted) and it guarantees that the item-level results are consistent with
the omnibus decision.
Within an RS-detected node, each item is first tested for any shift by
a joint LRT that frees that item's discrimination and
thresholds against the constrained model (df = K: one discrimination
plus K-1 thresholds). These joint p-values are adjusted across the
items in the node (p_adjust); an item is flagged when its
adjusted joint p-value is below alpha. Unflagged items are
"None".
Once an item is flagged, its type is read from the estimated
T1-versus-T2 changes on the IRT (a, b) metric: the absolute discrimination
change (discr_diff) indicates reprioritization and the
maximum absolute threshold change (thresh_diff) indicates
recalibration; both large is Both. A flagged item is always
given a real type – if both changes are below rs_threshold it takes
the larger one, so a significant item is never left untyped.
This is deliberate. A tempting alternative – decomposing the shift with
nested LRTs that free the discrimination or the thresholds in turn – does
not work here, because mirt parameterizes the graded model in
slope-intercept form where the intercept d = -a\,b. A pure
discrimination change (a moves, b constant) therefore forces the
intercepts to move, so any LRT that frees the intercepts fires for a
reprioritization item, spuriously flagging recalibration. The estimated
a and b changes, in contrast, separate the two shift types
cleanly (b = -d/a un-confounds them), which is why the type is read
from them. Detection remains a likelihood-ratio test; only the attribution of
which parameter moved uses the estimated changes, and both are
reported (discr_diff, thresh_diff, RS_magnitude) so the
classification is fully transparent.
Separating detection (is there a shift? – LRT), type (which parameter moved? – estimated change), and magnitude (how large? – effect size) is the point of the redesign.
Two adjustment layers are applied: global_p_adjust across nodes for
"in which subgroups does RS occur?" (default Bonferroni), and p_adjust
across items within a node for "which items shift?" (default Bonferroni; FDR
recommended for exploration). The component tests that assign the type are a
post-hoc decomposition of an already-flagged item and are read at
alpha.
McFadden's pseudo-R^2 = 1 - \ell_{uncon}/\ell_{con} is inherently
small in IRT (~0.02) and is best compared across nodes. AIC_{con} -
AIC_{uncon} is positive when the unconstrained model is preferred after the
parsimony penalty. Item-level discr_diff and thresh_diff give
the raw magnitude of the T1-vs-T2 parameter changes.
A list of class "rs_characterization" containing:
globalA data.frame with one row per terminal node
and columns:
NodeTerminal node ID.
nSample size in the node.
LL_constrainedLog-likelihood of the constrained (no-RS) model.
LL_unconstrainedLog-likelihood of the unconstrained (RS-allowed) model.
LRT_chi2Omnibus LRT statistic
-2(\ell_{con} - \ell_{uncon}).
LRT_dfDegrees of freedom (number of freed constraints).
LRT_pRaw omnibus p-value.
LRT_p_adjOmnibus p-value adjusted across nodes
(present only when global_p_adjust != "none" and there are
two or more nodes).
RS_detectedLogical: whether omnibus RS is detected at
alpha after adjustment. This flag gates item-level
testing.
pseudo_R2McFadden's pseudo-R^2,
1 - \ell_{uncon}/\ell_{con}.
AIC_diffAIC_{con} - AIC_{uncon}; positive
favours the unconstrained model.
mu_T2Latent mean shift at T2 (constrained model).
sigma2_T2Latent variance at T2.
cor_T1_T2Test-retest correlation of the latent trait.
converged_constrained, converged_unconstrainedConvergence flags for the two models.
item_levelA data.frame of item-level results, one
row per item only for RS-detected nodes (NULL if no
node was detected or item_level = FALSE):
Node, ItemNode ID and item number (1..M).
LRT_chi2, LRT_df, LRT_pThe joint
item test (free this item's discrimination and thresholds vs the
constrained model): statistic, df = K (1 discrimination plus
K-1 thresholds), and raw p-value. This is the item
detection test.
LRT_p_adjJoint p-value adjusted across items within
the node (p_adjust); an item is flagged when this is below
alpha.
RS_type"Recalibration", "Reprioritization",
"Both", or "None" – determined by the component LRTs
(see Details), never by a magnitude cut-point.
discr_diff, thresh_diffEffect sizes: the absolute T1-vs-T2 discrimination change and the maximum absolute threshold change (reported, not used to decide the type).
RS_magnitude"large"/"small" annotation
of a flagged item's effect size against rs_threshold
(NA for unflagged items).
parametersA named list (one element per node) of
constrained and unconstrained item-parameter matrices
(IRT parameterization).
n_items, alpha, p_adjust,
global_p_adjust, rs_thresholdThe settings used.
Olayinka Imisioluwa Arimoro olayinka.arimoro@ucalgary.ca, Lisa M. Lix, Tolulope T. Sajobi
Oort, F. J. (2005). Using structural equation modeling to detect response shifts and true change. Quality of Life Research, 14(3), 587–598.
Sprangers, M. A. G., & Schwartz, C. E. (1999). Integrating response shift into health-related quality of life research: a theoretical model. Social Science & Medicine, 48(11), 1507–1515.
Benjamini, Y., & Hochberg, Y. (1995). Controlling the false discovery rate: a practical and powerful approach to multiple testing. Journal of the Royal Statistical Society: Series B, 57(1), 289–300.
longitudinal_grmtree for Phase 1 (tree fitting),
print.rs_characterization for the print method,
prepare_longitudinal_data for data preparation,
p.adjust for p-value adjustment methods
library(grmtree)
data("grmtree_long_data", package = "grmtree")
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"))
ltree <- longitudinal_grmtree(
resp_wide ~ sex + age + residency + job +
education + comorbidity_count + ever_smoker,
data = ld, n_items = 8, control = grmtree.control(minbucket = 200))
# Default: Bonferroni across nodes and within-node; type from component LRTs
rs <- rs_characterize(ltree)
print(rs)
# FDR for the item search, Bonferroni across nodes
rs <- rs_characterize(ltree, p_adjust = "fdr", global_p_adjust = "bonferroni")
rs$global # omnibus per node (RS_detected gates the item tests)
rs$item_level # item detection + type + effect sizes, for detected nodes only
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.