Plot fitted MFRM results with base R
Usage
# S3 method for class 'mfrm_fit'
plot(
x,
type = NULL,
facet = NULL,
top_n = 30,
theta_range = c(-6, 6),
theta_points = 241,
title = NULL,
palette = NULL,
label_angle = 45,
show_ci = NULL,
ci_level = 0.95,
group = NULL,
diagnostics = NULL,
include_fit_measures = TRUE,
fit_stat = c("Infit", "Outfit"),
fit_scale = c("mnsq", "zstd"),
zstd_method = c("engine", "facets"),
include_person = FALSE,
person_subset = NULL,
top_n_person = 30,
person_labels = c("flagged", "all", "none"),
facet_labels = c("all", "flagged", "none"),
panel = c("combined", "facet"),
fit_range = c(0.5, 1.5),
zstd_cut = 2,
draw = TRUE,
preset = c("standard", "publication", "compact", "monochrome"),
renderer = NULL,
wright_style = c("native", "facets_style"),
category_labels = NULL,
rows_per_logit = 2L,
wright_range = NULL,
extreme_placement = c("ends", "estimate"),
persons_per_star = NULL,
...
)Arguments
- x
An
mfrm_fitobject fromfit_mfrm().- type
Plot type. Omit
type(or useNULL/"wright") for the primary native Wright map. Use"bundle","all", or"default"for the three-part fit bundle; otherwise choose one of"facet","person","step","wright","pathway","fit_pathway","ccc","ccc_surface", or"category_surface"."pathway"is the theta-to-expected-score display;"fit_pathway"is the fit-statistic-to-measure display.- facet
Optional facet name for
type = "facet".- top_n
Maximum number of facet/step locations retained by the native Wright map for compact displays. Step transitions are always retained; any omitted facet locations are counted in the returned
retentiontable and disclosed in the plot subtitle/note. UseInffor a complete all-level final map. The FACETS-style payload always retains every fitted facet and step location.- theta_range
Numeric length-2 range for pathway, CCC, and category-surface plot data.
- theta_points
Number of theta grid points used for pathway, CCC, and category-surface plot data.
- title
Optional custom title.
- palette
Optional color overrides.
- label_angle
Rotation angle for x-axis labels where applicable.
- show_ci
Whether to add approximate confidence intervals when available.
NULLselects the display-specific default:TRUEfor the primary native Wright map andtype = "fit_pathway", andFALSEfor the FACETS-style ruler and other plot types. Withrenderer = "facets", explicitly settingshow_ci = TRUEcreates a hybrid display: FACETS-style ruler grammar with mfrmr uncertainty intervals.- ci_level
Confidence level used when
show_ci = TRUE.- group
Optional grouping for
type = "wright"to overlay per-group person-density curves (DIF / DFF screening view). Either a column name (looked up first ingroup_datawhen supplied through..., then infit$prep$data) or a vector aligned withfit$facets$person. Ignored for othertypevalues and forwright_style = "facets_style", whose person column is a single FACETS-style star frequency. To pass the source data alongside, useplot(fit, type = "wright", group = "MyCol", group_data = <df>).- diagnostics
Optional output from
diagnose_mfrm(). When supplied, Wright-map standard errors and precision metadata reuse matching rows fromdiagnostics$measureswithout replacing fitted coordinates, while pathway plot data reusefit_measures,fit_status, andcurve_fit_statusinstead of recomputing diagnostics.- include_fit_measures
If
TRUE(default), pathway plot data include tidy fit-measure and fit-status tables for custom R graphics. Set toFALSEwhen only the curve coordinates are needed.- fit_stat
For
type = "fit_pathway", the horizontal fit statistic:"Infit"(default) or"Outfit".- fit_scale
For
type = "fit_pathway", use mean squares ("mnsq") or standardized fit ("zstd") on the horizontal axis.- zstd_method
For a ZSTD fit pathway, use the package engine degrees of freedom (
"engine", default) or the FACETS/Wright-Masters companion calculation ("facets"). The latter is a comparison aid, not a claim of complete FACETS output equivalence.- include_person
If
TRUE, include person rows in a fit pathway.- person_subset
Optional character vector of person IDs retained in a fit pathway before ranking.
- top_n_person
Maximum person rows retained in a fit pathway, ranked by distance from expected fit. Use
Inffor all selected persons.- person_labels
Person-label policy for a fit pathway:
"flagged"(default),"all", or"none".- facet_labels
Facet-level label policy for a fit pathway:
"all"(default),"flagged", or"none". This changes drawn labels only; all retained facet rows remain in the draw-free table.- panel
Fit-pathway layout:
"combined"(distinguish persons by shape) or"facet"(one base-graphics panel per facet).- fit_range
Mean-square review lines for a fit pathway.
- zstd_cut
Absolute ZSTD review line for a fit pathway.
- draw
If
TRUE, draw the plot with base graphics.- preset
Visual preset (
"standard","publication","compact", or"monochrome").- renderer
Wright-map renderer. Use
"native"(default) or"facets"for the FACETS Table 6-style visual layout. This is the canonical selector for new code. The native map is the primary display and includes available facet uncertainty by default. The closest FACETS-style visual usesshow_ci = FALSE.- wright_style
Wright-map renderer.
"native"preserves the package's histogram, point, range, and facet-SE display."facets_style"adds a FACETS Table 6-style text ruler with person-frequency stars, signed facet headers, and labeled score-transition lines. It is a visual-layout option, not a claim of numerical equivalence with FACETS. This explicit style name is equivalent torenderer = "facets". Addingshow_ci = TRUEto that style is an mfrmr/FACETS hybrid rather than the closest FACETS-style view.- category_labels
Optional score rubric labels used by
wright_style = "facets_style". Supply a named character vector keyed by original score, an unnamed vector with one label per retained category, or a data frame withScoreandLabelcolumns.- rows_per_logit
Number of FACETS-style ruler rows per logit.
- wright_range
Optional finite increasing length-2 logit range for the FACETS-style ruler.
NULLderives a range that contains the fitted data.- extreme_placement
In the FACETS-style renderer, place extreme-score persons at the ruler
"ends"or retain their fitted"estimate".- persons_per_star
Number of persons represented by one
*in the FACETS-style frequency column.NULLchooses a compact value automatically.- ...
Additional arguments ignored for S3 compatibility.
Value
Invisibly, an mfrm_plot_data object (default and for any
single type), or an mfrm_plot_bundle when
type = "bundle" / "all" / "default". Each returned fit plot
includes domain-specific readiness and an interpretation status in its
data payload.
Details
This S3 plotting method provides the core fit-family visuals for
mfrmr. When type is omitted, it returns the Wright map alone as
an mfrm_plot_data object (the most useful single figure for a
first inspection). Pass type = "bundle" (or "all" / "default")
to obtain the legacy three-plot mfrm_plot_bundle containing a
Wright map, pathway map, and category characteristic curves. The
compact native default records any omitted facet locations in
data$retention and annotates the subtitle and drawn figure; use
top_n = Inf to retain every fitted location in the final Wright map.
Native text labels remain collision-aware, so a retained point may be
unlabeled; its exact level and estimate remain available in the returned
plot data. When the fit records boundary-separated facet levels and no
display range was supplied, the native and FACETS-style maps use the same
robust automatic range and place those levels at ruler ends. Exact fitted
values and intervals remain in OriginalEstimate, CI_Lower, and
CI_Upper; DisplayEstimate, DisplayCI_Lower, DisplayCI_Upper, and the
clipping-status columns describe only the rendered coordinates. Endpoint
triangles and the plot footer disclose any omitted or clipped interval.
The returned object always carries machine-readable metadata through
the mfrm_plot_data contract, even when the plot is drawn
immediately.
Every fit-derived payload also carries data$fit_readiness,
data$interpretation_status, and data$interpretation_note. Availability
and interpretability are separate: when a numerical, data, design, or
stability gate requires review, the coordinates remain available for
diagnosis, but the call warns and marks the returned subtitle and drawn
title REVIEW ONLY.
type = "wright" shows persons, facet levels, and step thresholds on
a shared logit scale. Estimates are plotted as fitted, so the sign
convention follows the fit: higher person values indicate higher
ability, and higher non-person facet values indicate greater
severity/difficulty under the default negative facet orientation.
Facets listed in fit_mfrm(positive_facets = ...) are reversed
(higher values raise expected scores); state the active orientation in
figure captions when reporting.
Set renderer = "facets" (equivalently,
wright_style = "facets_style") for a line-printer-inspired common
ruler. That mode retains every facet location in its data and shows actual
(original, when scores were internally recoded) adjacent score transitions.
Its facets_style payload contains tidy ruler, person-frequency, facet,
step, mean-half-score, header, category-label, and settings tables for custom
graphics. RulerValue records the nearest discrete ruler row for
line-printer reconstruction, whereas step and midpoint lines are drawn at
their exact fitted DrawValue and step labels print that logit value. The
styling emulates the semantics of FACETS Table 6; estimates
and standard errors remain those produced by mfrmr. Use
show_ci = FALSE for the closest FACETS-style rendering. If
show_ci = TRUE is requested, interpret the result as a hybrid that adds
mfrmr uncertainty intervals to FACETS-style ruler grammar.
type = "pathway" shows expected score
traces and dominant-category regions across theta. This expected-score
display is distinct from the Bond-and-Fox-style fit-versus-measure
pathway: use type = "fit_pathway" for Infit/Outfit on the horizontal
axis and measure logits on the vertical axis. Its draw-free plot data
include person-selection settings, CI columns, and explicit SE-source
metadata. The expected-score pathway draw-free data also
includes pathway_long, pathway_annotations, fit_measures,
fit_status, and curve_fit_status, so R users can rebuild the pathway
map in ggplot2, plotly, or a report pipeline while keeping the same
underfit/overfit labels used by fit_measures_table(). type = "ccc" shows
category response probabilities. type = "ccc_surface" or
type = "category_surface" returns 3D-ready category-probability surface
data for external rendering; it deliberately does not add a
plotly/rgl dependency or replace the 2D CCC/pathway reporting figures. The
returned object includes category_support, interpretation_guide, and
reporting_policy tables so retained zero-frequency categories and
manuscript-use boundaries remain visible to beginners. The remaining
types ("facet", "person", "step", "shrinkage") provide
compact location-specific displays.
Typical workflow
Fit a model with
fit_mfrm().Use
plot(fit)to inspect the Wright map at a glance.Switch to
type = "pathway","fit_pathway","ccc", or"shrinkage"for the relevant follow-up figure, ortype = "bundle"for the three-plot overview when preparing a FACETS-style summary.
Further guidance
For a plot-selection guide and extended examples, see
mfrmr_visual_diagnostics and
vignette("mfrmr-visual-diagnostics", package = "mfrmr").
Examples
toy <- load_mfrmr_data("example_operational")
# Seven quadrature points keep this executable example short. For a final
# analysis, restore the default or a prespecified grid and review sensitivity.
fit <- fit_mfrm(
toy,
"Person",
c("Rater", "Criterion"),
"Score",
method = "MML",
model = "RSM",
quad_points = 7,
maxit = 30
)
wright <- plot(fit, draw = FALSE)
head(wright$data$locations)
#> # A tibble: 6 × 30
#> Group Label PlotType Estimate SE CI_Level SE_Method Measure_Source CI_Lower
#> <fct> <chr> <chr> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
#> 1 Rater R01 Facet l… -0.597 0.180 0.95 Observat… fit + observa… -0.950
#> 2 Rater R02 Facet l… -0.334 0.165 0.95 Observat… fit + observa… -0.657
#> 3 Rater R05 Facet l… 0.135 0.198 0.95 Observat… fit + observa… -0.253
#> 4 Rater R04 Facet l… 0.169 0.184 0.95 Observat… fit + observa… -0.192
#> 5 Rater R03 Facet l… 0.259 0.178 0.95 Observat… fit + observa… -0.0901
#> 6 Rater R06 Facet l… 0.368 0.217 0.95 Observat… fit + observa… -0.0570
#> # ℹ 21 more variables: CI_Upper <dbl>, Step <chr>, StepIndex <int>,
#> # BoundarySeparated <lgl>, XBase <dbl>, X <dbl>, OriginalEstimate <dbl>,
#> # BelowRange <lgl>, AboveRange <lgl>, DisplayEstimate <dbl>,
#> # DisplayLabel <chr>, OriginalCI_Lower <dbl>, OriginalCI_Upper <dbl>,
#> # DisplayCI_Lower <dbl>, DisplayCI_Upper <dbl>, CIClippedLower <lgl>,
#> # CIClippedUpper <lgl>, CIClipped <lgl>, BoundaryEnd <chr>,
#> # CISuppressed <lgl>, CIDisplayStatus <chr>
# Look for: persons clustered against the facet / step rows on the
# shared logit axis. Large gaps between the person density and
# the step / facet rails indicate weak targeting; ceiling /
# floor stripes mean the test is too easy / hard.
bundle <- plot(fit, type = "bundle", draw = FALSE)
bundle$wright_map$data$group_summary
#> # A tibble: 3 × 16
#> Group PlotType Min Q1 Median Q3 Max DisplayMin DisplayQ1
#> <fct> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Rater Facet level -0.597 -0.217 0.152 0.236 0.368 -0.597 -0.217
#> 2 Criterion Facet level -0.339 -0.110 0.118 0.169 0.221 -0.339 -0.110
#> 3 Step:Common Step thresh… -1.21 -0.520 0.166 0.603 1.04 -1.21 -0.520
#> # ℹ 7 more variables: DisplayMedian <dbl>, DisplayQ3 <dbl>, DisplayMax <dbl>,
#> # N <int>, XBase <dbl>, TargetGap <dbl>, DisplayTargetGap <dbl>
# Look for: pathway curves rising in the expected order with
# visible dominant-category bands; CCC curves peaking sequentially
# without one category being completely overlapped by neighbours.
surface <- plot(fit, type = "ccc_surface", draw = FALSE)
head(surface$data$surface)
#> Theta Probability ExpectedScore ScoreVariance Information CategoryInformation
#> 1 -6.00 0.9917645 1.008253 0.008219238 0.008219238 6.754698e-05
#> 2 -5.95 0.9913450 1.008674 0.008637056 0.008637056 7.458832e-05
#> 3 -5.90 0.9909043 1.009117 0.009075921 0.009075921 8.236015e-05
#> 4 -5.85 0.9904413 1.009582 0.009536874 0.009536874 9.093770e-05
#> 5 -5.80 0.9899549 1.010071 0.010021004 0.010021004 1.004038e-04
#> 6 -5.75 0.9894439 1.010585 0.010529453 0.010529453 1.108498e-04
#> CategoryInformationShare Slope Model Category CurveGroup CategoryIndex
#> 1 0.008218156 1 RSM 1 Common 1
#> 2 0.008635851 1 RSM 1 Common 1
#> 3 0.009074579 1 RSM 1 Common 1
#> 4 0.009535378 1 RSM 1 Common 1
#> 5 0.010019337 1 RSM 1 Common 1
#> 6 0.010527594 1 RSM 1 Common 1
#> CategoryScore SurfaceX SurfaceY SurfaceZ
#> 1 1 -6.00 1 0.9917645
#> 2 1 -5.95 1 0.9913450
#> 3 1 -5.90 1 0.9909043
#> 4 1 -5.85 1 0.9904413
#> 5 1 -5.80 1 0.9899549
#> 6 1 -5.75 1 0.9894439
surface$data$category_support
#> Category CategoryIndex CategoryScore ObservedCount ZeroObserved
#> 1 1 1 1 62 FALSE
#> 2 2 2 2 96 FALSE
#> 3 3 3 3 78 FALSE
#> 4 4 4 4 46 FALSE
#> SupportRole
#> 1 observed response category
#> 2 observed response category
#> 3 observed response category
#> 4 observed response category
# Look for: every retained category having `Observed > 0`; categories
# with zero observations are returned as a zero-observation slice and
# should not be interpreted as a real score region.
surface$data$interpretation_guide
#> Topic
#> 1 Axes
#> 2 Category dominance
#> 3 Zero-frequency categories
#> 4 Reporting use
#> 5 Renderer boundary
#> Guidance
#> 1 Read SurfaceX as theta/logit, SurfaceY as retained category index, and SurfaceZ as predicted category probability.
#> 2 A high SurfaceZ ridge marks the theta region where that category is most probable; compare with the 2D CCC/pathway view before making a reporting claim.
#> 3 All retained categories have at least one observed response in the fitted data.
#> 4 Use the 2D pathway or CCC figure as the default manuscript/report figure; use this surface as exploratory or teaching material.
#> 5 mfrmr returns the data contract only and does not execute plotly/rgl or any other interactive 3D renderer.
if (interactive()) {
plot(
fit,
type = "wright",
preset = "publication",
title = "Customized Wright Map",
show_ci = TRUE,
label_angle = 45
)
plot(
fit,
type = "pathway",
title = "Customized Pathway Map",
palette = c("#1f78b4")
)
plot(
fit,
type = "ccc",
title = "Customized Category Characteristic Curves",
palette = c("#1b9e77", "#d95f02", "#7570b3")
)
}
