The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
This vignette walks FACETS users through the closest
mfrmr workflow: preparing data, fitting an
RSM/PCM many-facet Rasch-family model with
FACETS-oriented settings, generating related diagnostic and reporting
tables, and reviewing the output-contract boundary between the two
systems. Bounded GPCM can be fit in mfrmr, but
its slope-aware score semantics are intentionally outside the score-side
FACETS output-contract route.
The software reference target for this migration boundary is FACETS 64-bit 4.5.1 (July 2026). A cited manual may retain its published 4.5.0 edition; software version and documentation edition are recorded separately. The coverage described here is not an external numerical-parity result.
The two stacks share the same psychometric framework but differ in operating model.
Before treating a legacy workflow as covered, inspect the public coverage boundary:
This matrix describes the availability of package-native output
surfaces. implemented does not by itself mean that the two
programs use the same estimand, conditioning, extreme-score rule,
degrees of freedom, or numerical contract.
| Concept | FACETS (Linacre 2026) | mfrmr |
|---|---|---|
| Input | Specification file plus data file | data.frame in long format |
| Estimation | JMLE by default | MML by default; JML is the closest
estimation route for a JMLE-oriented comparison |
| Fit-statistic basis | Residuals at JMLE estimates | Residuals at EAP person measures under MML (shrunken
toward the mean); refit with method = "JML" for a
JMLE-style residual basis |
| Models | Multiple model statements, rating scales, partial credit, and other response families can coexist | One response-model family per fit: RSM,
PCM, or bounded GPCM |
| Output | Tables 0-30 plus graphic files | Returned R objects with summary() and
plot() methods |
| Anchoring | Element/group anchors, rating-scale calibration, and reusable starting values | Element and group anchors; no general threshold/scale anchors or fixed-calibration starting-value bundle |
| Repeated cells | Multiple observations may be represented within a design cell | Exact Person-by-facet duplicates are retained but force Data review; distinguish legitimate repeats with an event/occasion facet |
| Bias / interaction | Table 14 | estimate_bias() and
bias_interaction_report() |
| Wright map / variable map | Graphic variable-map output | plot(fit, type = "wright") and
plot_wright_unified() |
| Fair average | Table 7 fair-M average | fair_average_table() |
| Reproducibility | Specification, input data, FACETS version, and recorded run environment/settings | build_mfrm_manifest() plus
build_mfrm_replay_script() |
If the goal is to translate a FACETS-style script with minimal R-side
plumbing, use run_mfrm_facets() (alias
mfrmRFacets()):
library(mfrmr)
data("mfrmr_example_operational", package = "mfrmr")
run <- run_mfrm_facets(
data = mfrmr_example_operational,
person = "Person",
facets = c("Rater", "Criterion"),
score = "Score",
model = "RSM",
method = "JML"
)
names(run)The wrapper returns the same fit_mfrm() and
diagnose_mfrm() objects that a step-by-step pipeline
produces, plus the iteration log, fair-average table, and rating-scale
table:
jml_status <- summary(run$fit, profile = "fit", detail = "brief")
jml_status$overview[, c(
"Model", "Method", "Converged", "InferenceReady",
"ConvergenceSeverity"
)]
jml_status$readiness
head(run$fair_average)method = "JML" is shown here for a JMLE-oriented
migration comparison. Do not infer readiness from Converged
alone: require InferenceReady = TRUE for the numerical gate
and review the terminal-gradient guidance when severity is
"review" or "fail". Numerical readiness does
not override a Data, Design, or Stability hold; use the readiness table
before interpreting or reporting the fit. For new analysis scripts,
prefer fit_mfrm(method = "MML") directly. MML integrates
over the person distribution under an N(0, 1) prior and exposes
per-person posterior SEs that JML cannot produce.
The mapping below covers the most common FACETS specification keywords.
Facets = 3
Models = ?,?,?,R5
Labels =
1, Examinee
1 = P01
...
2, Rater
1 = R1
...
3, Criterion
1 = Content
...
translates to:
fit_mfrm(
data = examinee_long,
person = "Examinee",
facets = c("Rater", "Criterion"),
score = "Score",
rating_min = 1,
rating_max = 5,
model = "RSM"
)Models = ?,?,?,R5 becomes model = "RSM" and
the R5 rating-scale declaration becomes
rating_min = 1, rating_max = 5. For a partial-credit
specification, pass model = "PCM" and identify the facet
that carries the step thresholds with step_facet = "Rater"
(or the appropriate facet name).
A FACETS D = 2, A = block:
D = 2
A = 1, 0.0
2, 0.5
becomes an anchors data frame:
anchors <- data.frame(
facet = "Rater",
level = c("R1", "R2"),
estimate = c(0.0, 0.5),
stringsAsFactors = FALSE
)
fit <- fit_mfrm(..., anchors = anchors)review_mfrm_anchors() validates and reports on the
anchor block before the fit runs, surfacing connectivity, overlap, and
minimum-sample issues.
For FACETS Table 14 bias output between Rater and Criterion, the closest mfrmr screening route is:
diag <- diagnose_mfrm(fit)
bias <- estimate_bias(fit, diag,
facet_a = "Rater", facet_b = "Criterion")
summary(bias)estimate_all_bias() enumerates every non-person facet
pair in one call.
For a shared-logit visual display of persons, facet levels, and step thresholds, first create the FACETS-organized summary and retain its result object:
review <- summary(fit, profile = "facets", detail = "brief")
res <- review$results
# Primary final-scale figure: all locations and available facet uncertainty.
plot(res, type = "wright", renderer = "native", show_ci = TRUE,
top_n = Inf, preset = "publication")plot_wright_unified() is the corresponding explicit
helper when the Wright map is the main figure. For readers who expect
the FACETS Table 6-style asterisk ruler and horizontal, rubric-labelled
category transitions, define one label for every retained original
score:
rubric_labels <- setNames(
your_rubric_labels,
fit$prep$score_map$OriginalScore
)
plot(res, type = "wright", renderer = "facets", show_ci = FALSE,
category_labels = rubric_labels, preset = "publication")show_ci = FALSE is the closest FACETS-style visual
grammar. Setting show_ci = TRUE deliberately creates a
hybrid display: the ruler is FACETS-style, but the intervals are mfrmr
uncertainty estimates. Neither renderer implies that FACETS performed
the estimation or that the two programs are numerically equivalent.
For the Bond-and-Fox-style follow-up requested by many FACETS users, put Infit on the horizontal axis and the measure on the vertical axis. Person rows remain opt-in:
plot(res, type = "fit_pathway", fit_stat = "Infit",
include_person = TRUE, top_n_person = 12,
person_labels = "none", facet_labels = "flagged")Use draw = FALSE or
plot_data(fit, type = "wright") when you need the
underlying coordinates for a custom ggplot2, base-R, or
Quarto graphic.
FACETS users often compare Infit/Outfit MnSq together with ZStd
columns. In mfrmr, treat MnSq as the primary fit statistic
and use the df/ZSTD columns to explain how the same MnSq values were
standardized. The direct review path is:
diag <- diagnose_mfrm(fit, residual_pca = "none", fit_df_method = "both")
fm <- fit_measures_table(fit, diagnostics = diag,
facet = "Rater", fit_df_method = "both")
fm$facets_table
fm$df_sensitive
plot(fm, type = "df_sensitivity")df_sensitivity reports the engine-vs-FACETS-style df
comparison row by row; df_sensitive keeps only rows where
the df convention changes the |ZSTD| flag or materially changes the ZSTD
interpretation. The same status taxonomy is used by
facets_fit_review(), so a table-oriented review and an
external FACETS comparison use the same language.
FACETS D = ..., G = group-anchor blocks for differential
facet functioning translate to the group_anchors argument
and the analyze_dff() follow-up:
group_anchors <- data.frame(
facet = "Criterion",
level = "Content",
group = c("Native", "Non-native"),
estimate = c(0.0, 0.0),
stringsAsFactors = FALSE
)
fit_g <- fit_mfrm(..., group_anchors = group_anchors)
dff <- analyze_dff(fit_g, diag, facet = "Criterion",
group = "FirstLanguage", method = "refit")When migrating an existing study,
facets_output_contract_review() checks whether the
package-generated report components satisfy the FACETS-style output
contract encoded in the package:
contract_review <- facets_output_contract_review(
fit,
diagnostics = diag,
branch = "facets"
)
summary(contract_review)
contract_review$missing_preview
contract_review$metric_checksThe resulting object reviews column coverage and package-native
metric checks. It is not a claim that mfrmr has reproduced
FACETS estimates numerically. For external numerical comparison, use an
exported FACETS fit table and facets_fit_review().
When that comparison involves an MML fit, remember that
mfrmr evaluates residual-based fit statistics at shrunken EAP person
measures while FACETS uses JMLE estimates, so MnSq differences can
reflect the residual basis rather than a fit-computation difference;
refit with method = "JML" before attributing such gaps. See
facets_fit_df_guide() for this boundary and for the
separate df/ZSTD standardization conventions.
If you already have a FACETS fit table on disk, read it first and then run the fit review. This does not run FACETS; it consumes an exported or otherwise harmonized table.
facets_fit <- read_facets_fit_table(
"score.2.txt",
facet_map = c("1" = "Person", "2" = "Rater", "3" = "Criterion")
)
review <- facets_fit_review(
fit,
diagnostics = diag,
facets_fit = facets_fit,
external_zstd_tolerance = 0.05
)
review$df_sensitivity
review$df_sensitive
review$external_table_quality
review$external_comparison
plot(review, type = "df_sensitivity")Use external_comparison for the supplied FACETS table
and df_sensitivity for the engine-vs-FACETS-style df
convention check. This separation keeps external numerical differences
distinct from ZSTD differences caused by df standardization.
external_table_quality is the first place to look if the
FACETS export only contains ZStd and T.Count columns, or if duplicate
Facet x Level rows were supplied.
For traceability or downstream tools that expect FACETS output files,
facets_output_file_bundle() writes a parallel set of
fixed-width or CSV exports:
files <- facets_output_file_bundle(
fit,
diagnostics = diag,
out_dir = tempdir(),
include = c("graph", "score")
)For RSM and PCM the score-side helpers are available. Under bounded
GPCM the score-side bundle is intentionally restricted; see
?gpcm_capability_matrix and the
mfrmr-gpcm-scope vignette for the documented
limitation.
After a FACETS-oriented package-native fit is in hand, the recommended mfrmr reporting workflow extends the analysis with:
review_mfrm_anchors() before anchored fitting, and
detect_anchor_drift() / plot_anchor_drift()
when common elements define a cross-form or cross-wave link.diagnose_mfrm(diagnostic_mode = "both") for the strict
marginal screen alongside the residual stack.rating_scale_table(),
category_structure_report(), and
category_curves_report() for category-functioning
evidence.fair_average_table() when FACETS Table 12-style
fair-average review is needed.plot(fit, type = "wright") or
plot_wright_unified() for a variable-map view of targeting
and threshold placement.estimate_bias(),
bias_interaction_report(), and
bias_pairwise_report() when FACETS Table 14-style local
interaction screening is substantively relevant.reporting_checklist() for a manuscript-readiness
summary.build_apa_outputs() for Method and Results paragraphs
and APA tables.build_mfrm_manifest() and
build_mfrm_replay_script() for the reproducibility bundle
alongside the FACETS-style handoff out of the box.The mfrmr-workflow vignette covers the full sequence end
to end; the mfrmr-reporting-and-apa vignette focuses on
manuscript preparation; the mfrmr-linking-and-dff vignette
covers anchoring, drift, and DFF in detail.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.