Plot anchor drift or a screened linking chain
Source:R/api-plotting-anchor-qc.R
plot_anchor_drift.RdCreates base-R plots for inspecting anchor drift across calibration waves or visualising the cumulative offset in a screened linking chain.
Arguments
- x
An
mfrm_anchor_driftormfrm_equating_chainobject.- type
Plot type:
"drift"(dot plot of element drift),"chain"(cumulative offset line plot), or"heatmap"(wave-by-element drift heatmap).- facet
Optional character vector to filter drift plots to specific facets.
- preset
Visual preset (
"standard","publication", or"compact").- draw
If
FALSE, return the plot data invisibly without drawing.- ...
Additional graphical parameters passed to base plotting functions.
Value
A plotting-data object of class mfrm_plot_data. With
draw = FALSE, result$data$table contains the filtered drift or chain
table, result$data$matrix contains the heatmap matrix when requested,
and the payload includes package-native title, subtitle, legend,
and reference_lines.
Details
Three plot types are supported:
"drift"(formfrm_anchor_driftobjects): A dot plot of each element's drift value, grouped by facet. Horizontal reference lines mark the drift threshold. Red points indicate flagged elements."heatmap"(formfrm_anchor_driftobjects): A wave-by-element heat matrix showing drift magnitude. Darker cells represent larger absolute drift. Useful for spotting systematic patterns (e.g., all criteria shifting in the same direction)."chain"(formfrm_equating_chainobjects): A line plot of cumulative offsets across the screened linking chain. A flatter line indicates smaller between-wave shifts; steep segments suggest larger link offsets that deserve review.
Which plot should I use?
Use
type = "drift"with anmfrm_anchor_driftobject to review flagged elements directly.Use
type = "heatmap"with anmfrm_anchor_driftobject to spot wave-by-element patterns.Use
type = "chain"with anmfrm_equating_chainobject afterbuild_equating_chain()to inspect cumulative offsets across waves.
Interpreting plots
Drift is the change in an element's estimated measure between calibration waves, after accounting for the screened common-element link offset. An element is flagged when its absolute drift exceeds a threshold (typically 0.5 logits) and the drift-to-SE ratio exceeds a secondary criterion (typically 2.0), ensuring that only practically noticeable and relatively precise shifts are flagged.
In drift and heatmap plots, red or dark-shaded elements exceed both thresholds. Common causes include rater drift over time, item exposure effects, or curriculum changes.
In chain plots, uneven spacing between waves suggests differential shifts in the screened linking offsets. The \(y\)-axis shows cumulative logit-scale offsets; flatter segments indicate more stable adjacent links. Steep segments should be checked alongside
LinkSupportAdequateand the retained common-element counts before making longitudinal claims.For drift objects, it is usually best to read
summary(x)first and then use the plot to see where the flagged values sit.
Typical workflow
Build a drift or screened-linking object with
detect_anchor_drift()orbuild_equating_chain().Start with
draw = FALSEif you want the plotting data for custom reporting.Use the base-R plot for quick screening and then inspect the underlying tables for exact values.
Further guidance
For a plot-selection guide and a longer walkthrough, see
mfrmr_visual_diagnostics and
vignette("mfrmr-visual-diagnostics", package = "mfrmr").
Examples
toy <- load_mfrmr_data("example_core")
people <- unique(toy$Person)
d1 <- toy[toy$Person %in% people[1:12], , drop = FALSE]
d2 <- toy[toy$Person %in% people[13:24], , drop = FALSE]
fit1 <- fit_mfrm(d1, "Person", c("Rater", "Criterion"), "Score",
method = "JML", maxit = 10)
#> Warning: Optimizer did not fully converge (code = 1). Consider increasing maxit (current: 10) or relaxing reltol (current: 1e-06).
fit2 <- fit_mfrm(d2, "Person", c("Rater", "Criterion"), "Score",
method = "JML", maxit = 10)
#> Warning: Optimizer did not fully converge (code = 1). Consider increasing maxit (current: 10) or relaxing reltol (current: 1e-06).
drift <- detect_anchor_drift(list(W1 = fit1, W2 = fit2))
#> Warning: Thin linking support between 'W1' and 'W2': fewer than 5 retained common elements in Criterion, Rater.
drift_plot <- plot_anchor_drift(drift, type = "drift", draw = FALSE)
class(drift_plot)
#> [1] "mfrm_plot_data" "list"
names(drift_plot$data)
#> [1] "plot" "table" "title" "subtitle"
#> [5] "legend" "reference_lines" "preset" "plot_name"
chain <- build_equating_chain(list(F1 = fit1, F2 = fit2))
#> Warning: Thin linking support between 'F1' and 'F2': fewer than 5 retained common elements in Criterion, Rater.
chain_plot <- plot_anchor_drift(chain, type = "chain", draw = FALSE)
head(chain_plot$data$table)
#> # A tibble: 2 × 2
#> Wave Cumulative_Offset
#> <chr> <dbl>
#> 1 F1 0
#> 2 F2 -0.0705
if (interactive()) {
plot_anchor_drift(drift, type = "heatmap", preset = "publication")
}