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. GPCM can be fit in mfrmr, but its
slope-aware score semantics are intentionally outside the score-side
FACETS output-contract route.
The local numerical comparison uses FACETS 64-bit 4.5.0. The online update history lists 4.5.3 (October 2026); a current web manual is not a version-pinned executable specification. The 4.5.1 history says the gtheory interface was replaced while the linked help still names gtheory. Keep the executable, manual edition and statistical decomposition distinct. The bounded executed comparisons below do not certify all FACETS options or versions.
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 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 13 cell effects; Table 14 pairwise comparisons | estimate_bias() and
bias_interaction_report(); conditional screens with the
differences below |
| Wright map / variable map | Graphic variable-map output | plot(fit, type = "wright") and plot() |
| 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() |
read_facets_results() reads supported Scorefile exports
without refitting. The included small synthetic example has one row per
facet element, with fixed anchors and extreme scores. Inspect
summary() for available measures and fit statistics; these
counts do not assess the quality of the source analysis.
library(mfrmr)
score_directory <- system.file("extdata", "facets-example", package = "mfrmr")
facets_result <- read_facets_results(score_directory,
facet_map = c("Person", "Rater", "Task"), source_version = "4.5.0")
summary(facets_result)
facets_result$table[, c("Facet", "ElementID", "Label", "Estimate", "SourceStatus")]Squares identify FACETS Status=1, which can denote a
direct anchor or a member of a group anchor. The import retains
SourceStatus = "anchored", but this does
not establish that the individual’s measure was fixed.
A group member may be estimated around the constrained mean.
GroupRaw can also be a reporting group; its value, the
number of imported group members and a reported SE cannot identify the
anchor subtype. Inspect the original Labels= for the anchor
mode and Table
7 for row annotations. A Table 7 G annotation alone need not
distinguish the G and X input modes. summary() therefore
calls this count AnchorFlagged, replacing
Anchored from earlier candidate versions. For saved
imports, call plot() again to refresh the legend and notes;
the source values and availability remain intact.
Extreme members of G/X groups can carry Status -2/-3 instead of 1, so
AnchorFlagged is not a count of every member of an anchored
group. Their triangles identify the source’s extreme-score status. A
finite reported location does not establish which adjustment produced
it: G and X can report different locations. The import preserves these
locations and marginal SEs, while keeping their Infit/Outfit
placeholders unavailable for fit plots.
type = "fit" shows measure versus Infit or Outfit;
type = "infit_outfit" compares the two mean squares.
Inspect the plotted rows and unavailable reasons before interpreting
missing points:
fit_points <- plot_data(facets_result, component = "plot_data",
type = "infit_outfit", facets = "Person")
fit_points[, c("Label", "Infit", "Outfit", "Available", "Reason")]
plot_data(facets_result, component = "notes")For your own analysis, supply named comma/tab/semicolon files, a
vector of per-facet exports, or a directory of score.N.txt
files. Use the actual source encoding (for example
encoding = "CP932" for an applicable Japanese Windows
export). For FACETS text output, the following specifications retain the
column headings and quoted labels needed by the reader:
Scorefile = score.txt
Heading lines = Yes
QM = Double
CSV = Semicolons
CSV = Commas or CSV = Tabs selects the
other supported separators. Keep the generated facet heading line; the
Scorefile reader finds the column header. Check that the files exist and
that their labels are intact before importing. A successful process exit
alone does not establish a successful export. The reader’s
encoding converts an existing file; it neither changes
FACETS input settings nor restores labels already lost in the external
output.
You can keep FACETS’ exported IDs and assign local display names in
R. The map uses the imported Facet and
ElementID, not row positions or source labels. Store IDs as
text to retain any leading zeros. Here only two Persons are renamed;
other elements retain their original labels:
display_names <- data.frame(Facet = "Person", ElementID = c("1", "2"),
DisplayLabel = c("受検者 甲", "受検者 乙"))
labelled <- plot(facets_result, facets = "Person",
label_map = display_names, draw = FALSE)
labelled$data$plot_data[, c("ElementID", "Label", "DisplayLabel")]The original result and its labels remain unchanged;
labelled$data$label_map retains the supplied
correspondence. Unknown or repeated keys are errors. Repeated display
names are distinguished by element key. Only measure plots draw element
labels; other element plots keep the names in their returned data. This
map does not apply to Graphfile category labels.
Japanese text also needs a graphics device and font with the required glyphs. With Cairo support and Meiryo installed on Windows, save the plot as follows; choose an available Japanese font on another system. Check the saved file for missing glyphs. This does not require Japanese input to FACETS or change its results. See R’s Cairo device documentation.
png("facets-japanese.png", width = 7, height = 5, units = "in", res = 200,
type = "cairo", family = "Meiryo")
plot(facets_result, facets = "Person", label_map = display_names)
dev.off()
cairo_pdf("facets-japanese.pdf", width = 7, height = 5, family = "Meiryo")
plot(facets_result, facets = "Person", label_map = display_names)
dev.off()Fixed-width imports require the supported ASCII all-field layout.
Element IDs distinguish duplicate labels. Source signs and reported
values are preserved; no automatic recentering or sign reversal takes
place. A point-only Wright map (type = "wright")
additionally requires common_scale = TRUE at import after
checking compatible units and origins in the original FACETS
specification.
Extreme-score rows are flagged; their status does not identify the
adjustment rule used by FACETS. Their fit values can be placeholders and
are unavailable in fit plots. Source SEs are retained in the table; no
confidence intervals are constructed. These descriptive results do not
provide new-person scoring, threshold reconstruction or validation of
the FACETS analysis. saveRDS(facets_result, ...) preserves
the complete result; as.data.frame(facets_result) exports
its element table. See ?read_facets_results and
?plot.mfrm_facets_results for the supported scope.
For category-probability and expected-score curves, export a FACETS Graphfile with headings. This separate synthetic PCM example contains one coordinate row per scale and reported measure; it is a different analysis from the binary score example above.
graph_path <- system.file("extdata", "facets-graph-example", "graph.txt",
package = "mfrmr")
facets_curves <- read_facets_results(graph_file = graph_path,
source_version = "4.5.0")
summary(facets_curves, component = "curves")Use type = "expected" for the exported expected-score
curve. Inspect the actual coordinates and source-consistency checks
with:
expected_points <- plot_data(facets_curves, "plot_data",
type = "expected", scales = 1)
head(expected_points[, c("Scale", "Measure", "Value", "Available", "Reason")])
head(facets_curves$graph$diagnostics)The reader preserves Graphfile scale numbers and category codes. A
scale number identifies a Table 8 subtable; it does not automatically
identify an item. Even binary exports may use category codes 1/2 instead
of the original 0/1 responses. Check the source specification before
interpreting expected scores. The graph Measure axis is separate from
the element measure declarations; importing both files does not align
them. When both exports belong to your analysis, supply
file = ... and graph_file = ... in one call,
after checking that correspondence.
Missing or invalid coordinates remain in
as.data.frame(facets_curves, component = "curves") and
break the plotted lines. Probability sums are checked using exported
decimal precision, without renormalizing. These checks do not certify
model fit; connecting segments do not calculate new model
predictions.
Match the statistical question before comparing numbers. A FACETS-style table name does not guarantee the same calculation. For an existing FACETS study, first align the response model, retained categories, orientation, anchors and centering, observations and replication weights, and extreme-score treatment. Compare unrounded logits before user scaling. Then compare response probabilities, mean squares, df and standardization separately. FACETS uses score-residual and measure-change convergence criteria; an optimizer’s success code alone does not establish agreement with them.
The corrected candidate has a bounded executed comparison against FACETS 4.5.0: complete binary ordinary JML data with unit weights and matched signs. Locations, SEs, MnSq, PTMEA and WHEXACT YES/NO agree within external report precision; bias estimates, baseline expected scores and the zero-bias summary also agree. This is not a drop-in equivalence claim for other models or options.
| Quantity | Current definition | Consequence for interpretation |
|---|---|---|
| Fit ZSTD | Diagnostics default to FACETS fourth-moment df.
whexact = FALSE is YES and TRUE is NO; both
use the cube root. |
Use fit_df_method = "engine" and
whexact = "legacy_linear" to reproduce the former
engine/TRUE convention. "both" exposes df sensitivity.
Cutoff decisions may change. |
| Point-measure correlation | PTMEA now uses the oriented measure sum for each response, including Person rows. | Old Person-only correlations must be recomputed. |
| Displacement | Updates now include facet orientation and the score derivative. | Negative-facet released estimates now move in the correct coordinate; this is still a conditional one-step diagnostic. |
| Facet chi-square | The statistic and df use the same finite estimates and positive finite SEs. | Excluded levels are reported; a missing SE cannot silently contribute df. |
| Expected point-measure correlation | Ordinary additive RSM/PCM JML exposes PTMEAExpected and
PTMEAExpectedAsymptotic. The former includes Linacre’s
published (N-2)/N variance correction with frequency count
N. |
Matched PCM output agrees within print precision. This is a conditional reporting approximation; below count two or with unbounded/incomplete calibration, the corrected reference remains unavailable. Recreate diagnostics to obtain it. |
| PCM fair averages | Expectations under administered scales are averaged using response weights. | Averaging thresholds first can give different scores and is no longer used. |
| Bias cell tail area | Continuous weighted count minus 1 is retained;
DFDisplay separately rounds positive df for display
comparison. FACETS 4.5.0 reports count 8 and df 7 in the executed
example, although Table 13 says count minus 2. |
Checked fractional-count native tails match an integer-df finite sum extended outside its valid domain and can change a 0.05 screen. mfrmr retains the continuous Student reference and records probability availability; nonpositive df withhold the tail. These are conditional screens, not calibrated fairness tests. |
| Bias expected score | Expctd Score and Obs-Exp Average now refer
to the main analysis. |
Separate after-bias columns show how much of that departure the shift explains. |
| Bias summary chi-square | Tests the cells against zero with df equal to the cell count. | A common nonzero bias no longer disappears through centering. |
| Pairwise bias | Uses target + bias/TargetSign, conditional cell SEs and
modified Rasch-Welch df rounded down, matching FACETS 4.5.0
unequal-count results. |
df_method = "classical" retains the earlier continuous
Welch reference. Missing references withhold comparisons; neither mode
includes calibration uncertainty. |
| Unexpected responses | Defaults to abs(z) >= 3,
rule = "residual". |
The older probability OR rule is opt-in; rankings now treat tied modes symmetrically. |
Definitions are given in the official WHEXACT, point-measure, Table 7, fair-average, and Table 13 documentation. The count-minus-1 observation above describes the executed version and example, not a correction to the external manual or a claim about every FACETS version.
Recompute diagnose_mfrm() from a saved fit, then
recreate estimate_bias() and reports. Corrected native
diagnostics and bias results carry calculation_version = 2;
do not add that field manually to old values. These diagnostic changes
do not require refitting the calibration.
For a negatively oriented rater, the model predictor contains
-severity + bias, so its context-specific severity is
severity - bias. The Table 14
examples make this direction explicit. Reversing the contrast leaves
a two-sided tail area unchanged but reverses the substantive feedback.
Pairwise df also needs its own version specification: the current t-statistics
manual describes a 2025 modification alongside classical Welch. The
executed FACETS 4.5.0 unequal-count comparison confirms the modified
formula and integer truncation for the tail area.
DFUnrounded and DFMethod retain that choice;
df_method = "classical" reproduces the earlier
reference.
Corrected pairwise tables carry CalculationVersion = 3.
Recreate build_fixed_reports() and
bias_pairwise_report() from the current bias bundle. First
recreate old bias bundles from the saved fit and current diagnostics; no
main calibration refit is needed. Historical report values are not
automatically corrected by reloading them. Local and contrast SEs
describe conditional cell uncertainty; calibration uncertainty and
cross-cell covariance are not propagated. The earlier claim that these
contrasts were generally conservative was incorrect. Check
ScreenUnavailable in the pairwise summary before reading
Flagged; the summary covers the full family even when
top_n limits the table.
The Table 4
rule and its default
threshold now match the native residual-only default. To retain the
exploratory probability screen, request
abs_z_min = 2, prob_max = .30, rule = "either". A fixed .30
cutoff has no universal interpretation: five equally likely categories
each have probability .2, so it flags every response. For tied modes,
MostLikely is missing, MostLikelyCount records
the tie and CategoryGap uses the nearest mode. This ranking
cannot decide which rater is unfair or which ratings to remove.
Category reports now distinguish the observed generating-measure
average (AvgMeasure), model-expected generating-measure
average (ExpectedMeasure), Person-only mean and expected
response score. Category residual MnSq is descriptive: conditioning on
the observed category removes the universal unit baseline, so category
ZSTD and its flags are unavailable. This does not turn a missing fit
flag into evidence that the category functions well.
In category_structure_report(),
MedianThreshold now means a cumulative 50% boundary;
AndrichThreshold retains the adjacent-category step.
Recreate saved structure reports. Half-score crossings outside
theta_range stay missing, and modal peaks describe only the
requested grid. The random chi-square likewise cannot establish
normality: with equal SEs and positive adjusted variance it is fixed by
the number of eligible elements, regardless of shape. Chi-square
summaries retain unavailable flags and use the full family before
truncation.
For external files, fixed-field import requires validated all-field
headings and element number after the statistics; other layouts should
use named delimited columns. Native score exports contain observations,
not the elements in a FACETS Scorefile. Native Tables 5 and 11 omit
parts of FACETS’ response moments and variance reports. A single
co-observation graph component also does not prove identification;
inspect the fitted design audit. The historical
conditional_probability plotting alias is ordinary P(k),
not FACETS’ adjacent-conditional probability; use ccc to
name the native quantity clearly.
Match denominators as well as cutoffs. FACETS
Totalscore defaults to No, while
fair_average_table() defaults to
totalscore = TRUE. Native raw
TotalScore/TotalCount and weighted
WeightdScore/WeightdCount are distinct;
ObservedAverage uses the weighted values. Scores 0 and 2
with weights 1 and 3 have raw total/count 2/2 but weighted total/count
6/4 and average 1.5. Keeping both counts is useful for describing the
data, provided the comparison uses the same replication
semantics and extreme-row inclusion. Weights do not by themselves
establish the independence or sampling uncertainty of repeated
ratings.
xtreme_method = "display" retains mfrmr’s
average-score target and leaves fair scores unchanged. For ordinary
additive RSM/PCM JML,
fair_average_table(..., xtreme = .3, xtreme_method = "facets")
instead solves a corrected weighted-total equation using actual
administered calibration and the element’s minimum positive eligible
weight. It updates that element’s fair scores and reports conditional
information SEs while retaining primary estimates and fixed anchors.
estimate_bias(..., xtreme = .5) separately extrapolates
extreme cells within the specified search limits. Group-mean anchors and
fitted interactions are unsupported. Matching origin constraints
resolves the checked interior partial-anchor differences; broader
extreme-score anchoring and exclusion remain unverified. Neither its
reporting SE nor an optimizer’s finite stopping value supplies
uncertainty for the original infinite MLE or a validated decision
probability.FairMReferencePersons and FairMExcludedPersons
identify the reference, and no eligible Persons leaves the score
unavailable. The reference describes this finite subset; it is not an
estimate of the mean ability of an unrestricted population.RealSE = ModelSE * sqrt(max(Infit, 1)) agrees with the
FACETS enlargement
formula, but this does not make their underlying ModelSE equal or
make RealSE a general dependence-robust SE. A supplied fixed anchor is
not a newly estimated parameter; missing sampling SE does not establish
that the external anchor is known without error.Record the estimand, method, scale, reference population, eligibility, statistic and exact comparison rule with a decision. Read both the magnitude of the departure and its uncertainty. A fit flag or a bias-screening tail area alone does not identify an unfair rater or justify deleting ratings.
Use unrounded values for an available calculation. A FACETS token
such as 2.00 at a ZSTD cutoff cannot reveal whether the
unreported value was below or above 2; retain a boundary-indeterminate
comparison. Do not choose between YES/NO, df conventions, priors or
category recoding after seeing which one crosses a desired cutoff. A
change of convention that changes a decision requires a stated rationale
and sensitivity report, even if both calculations are internally valid.
Missing uncertainty is not evidence that a criterion has been met.
For pass/fail work, keep the operational cut rule separate from a
model’s expected score or fair average.
classification_table() describes its supplied calibrated
rating plan and cut rules; posterior scoring answers a different
conditional question. Neither automatically validates the cuts, future
rating plan or substantive consequences.
FACETS’ estimation
documentation states that it does not correct JMLE estimation bias.
Accordingly, ordinary method = "JML" under matched RSM/PCM
models, anchors and origin constraints is the relevant mfrmr comparison.
Equal fitted values establish neither unbiased estimation nor calibrated
intervals. More Persons alone need not remove the incidental-parameter
bias when each Person still supplies few ratings.
These operations have different targets and should be recorded separately:
| Operation | What it changes | Relationship to mfrmr |
|---|---|---|
| FACETS ordinary JMLE | Solves the joint estimation equations. | Compare with ordinary RSM/PCM JML under aligned model and numerical controls. |
FACETS Xtreme |
Supplies finite extrapolations for extreme totals. | xtreme_method = "facets" implements the documented
reporting convention within its supported scope; it is not a general
estimation-bias correction. |
mfrmr jml_correction_order |
Changes the profiled structural score equation. | An experimental GPCM method requiring the same facet to own steps and slopes; it does not reproduce FACETS JMLE. |
For the corrected route,
fit_mfrm(model = "GPCM", method = "JML", jml_correction_order = ...)
solves the adjusted equation described in ?fit_mfrm. This
is an existing implementation, not an RSM/PCM correction switch. It
currently excludes anchors and supplies local-root RootSE,
not validated structural-truth confidence intervals. Its
fixed/random-roster covariance describes repeated independent Person
cohorts; the common-plan delta procedure instead holds each Person’s
ability fixed across repeated responses. Passing that RootSE into the
common-plan interval calculation would change both the estimator and the
sampling target. Corrected JML is therefore not admitted by
confint.mfrm_fair_average().
The benefit of retaining both estimators is that external
compatibility and a possible reduction in incidental-parameter bias can
be studied separately. The cost is a distinct mathematical, numerical
and inference contract: correction order, remaining bias, variance and
solver stability all require evaluation. FACETS agreement cannot select
the correction order or qualify its uncertainty. Keep ordinary JML as
the comparison/default route and select corrected JML explicitly within
its documented scope. FACETS’ separate Bias interaction
analysis also should not be confused with correction of an estimator’s
bias.
TAM’s tam.jml() helps check the common RSM/PCM
likelihood, but its default corrections differ from ordinary mfrmr JML.
Match category support, cumulative difficulties, anchors and location
constraints first. The TAM
documentation describes its separate adjustment and bias
arguments.
| Comparison | What to align or retain |
|---|---|
| Ordinary interior JML | Use bias = FALSE and adj = 0 for the TAM
comparison. This requires finite interior solutions; it is not a recipe
for extreme totals. |
| Category support | If a Rater-Task column lacks the highest allowed category, inspect
returned A and B. With custom full-category
A, supply intended category scores in B; a
generated score matrix can define a different model. |
| Classical correction | The checked TAM bias = TRUE multiplies free item
coefficients by (I-1)/I, using response-column count. Its
returned Person estimates and SEs are not all recomputed at the
corrected coefficients. This is distinct from mfrmr’s profile-score
adjustment selected by jml_correction_order. |
| Extreme totals | TAM adj modifies calibration scores. mfrmr’s explicit
xtreme_method = "facets" conditions on saved calibration
and retains infinite primary estimates. Matched extrapolations do not
establish matched calibration procedures. |
| Person uncertainty | Compare TAM theta with MLEs and retain WLE
separately. errorWLE is not the MLE’s SE. Conditional
information, joint sampling uncertainty and coverage are separate
questions. |
| Fit statistics | tam.jml.fit(trim_val = Inf) exposes untrimmed residual
fit; its default trims large squared residuals. Unit-weight untrimmed
fit has a matched fourth-moment transform, without certifying every
FACETS reporting field. |
| Weights | TAM normalizes Person pweights; these are not arbitrary
response replication weights. With missingness and unequal weights, its
checked item Outfit denominator also differs from normalization by
observed weight sum. |
| Anchors | Match the origin constraints as well as fixed values. FACETS ignores
centering on anchored facets; ordinary mfrmr JML offers
centering_scope = "anchor_origin" for direct and group
anchors. This does not extend the executed TAM group-anchor comparison
scope. The checked TAM version routes Person anchors through version 1;
an all-item-fixed case with a Person anchor fails. |
Executed TAM 4.3-25 comparisons support close ordinary-JML agreement
for matched complete/sparse RSM/PCM designs and supported partial Person
anchors. They do not establish general coverage, every FACETS anchoring
convention, or a new JML import route: import_tam_fit()
remains MML-only. Retain unavailable uncertainty instead of substituting
WLE SEs or conditional information for it.
Inspect returned anchors too. In the checked TAM 4.3-25 version-1
path, theta.fixed with xsi.fixed = NULL still
recenters every Person after an update, moving a supplied Person anchor.
A free-intercept probe did not retain the anchor and reached its
iteration limit. An empty fixed-item matrix prevented that recentering
in this version, but the probe still did not reach the required
score-equation accuracy within the same limit. This is a
version-specific diagnostic observation, not a general workaround
recommendation. The matching reference instead uses an independently
fitted unanchored TAM solution translated to the specified Person
origin, preserving every response probability. Keep that algebraic
comparison separate from a successful direct anchored TAM execution.
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-readiness criteria 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. Choose the
estimator for the intended question. The default MML route integrates
over a fixed N(0, 1) population and exposes Person posterior SDs; other
supported population specifications must be selected explicitly. Its
assumptions and shrinkage must be justified for the target population. A
posterior SD and a JML sampling SE are different quantities.
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). The declaration preserves the intended
category map, but it is not a threshold anchor. A missing boundary
category remains review evidence for the separate element-boundary
contract. A missing internal category in a polytomous fitted ladder
creates an unsupported adjacent-step contrast and stops fitting before
optimization. Review or revise the data support rather than copying
FACETS category-dropping behavior implicitly.
A FACETS Labels= block with direct anchoring:
Labels =
2, Rater, A
1 = R1, 0.0
2 = R2, 0.5
*
becomes an anchors data frame:
anchors <- data.frame(
Facet = "Rater",
Level = c("R1", "R2"),
Anchor = c(0.0, 0.5),
stringsAsFactors = FALSE
)
fit <- fit_mfrm(..., method = "JML", anchors = anchors,
centering_scope = "anchor_origin", anchor_policy = "error")Use labels that match the input data. Anchor is a
recognized value column; estimate is not. A malformed
nonempty anchor schema stops fitting. For migration, also use
anchor_policy = "error" for review issues and inspect the
normalized anchors before interpreting results. These values must be on
mfrmr’s logit scale. Convert user-scaled FACETS measures back using the
original origin and multiplier; copying a scaled number into a logit
anchor changes the model.
FACETS disables
centering on anchored facets. The explicit
"anchor_origin" option follows this rule for direct and
group anchors in ordinary additive RSM/PCM JML. One unanchored, active
facet must be declared noncenter_facet; other unanchored
facets remain centered. Thus, a Person anchor requires a different
noncenter facet, such as Rater. Merely adding a Person anchor while
centering every other facet can produce FACETS overconstraint warnings
and nonzero score residuals. Correcting that specification resolved the
checked sparse interior RSM/PCM discrepancies. Multiple fixed values may
impose substantive restrictions beyond the origin. Other estimators and
fitted interactions are outside this option. An origin anchor does not
guarantee a finite maximum. Without Person group constraints, if every
retained response of the Person anchors is at the same declared minimum
or maximum, free Person and noncenter-facet locations can diverge
together while respecting the fixed values. This case stops before
optimization, without requiring lpSolve. An extreme anchor
with additional interior or opposite-boundary anchor support does not by
itself meet this rule; other boundary diagnostics still apply.
In matched sparse RSM/PCM examples, FACETS 4.5.0 retained all
observations and the extreme Person’s fixed value. Its reported
calibration implied an expected anchor total of about 0.299 for an
observed total of 0, or 17.701 for 18. These values are consistent with
the specified Xtreme=0.3, but the ordinary likelihood can
still increase along a direction that preserves the anchors. The exact
internal adjustment is not established by this comparison. mfrmr
therefore does not reproduce these finite outputs as ordinary JML
estimates. This is a difference in estimation behavior, not an import or
rounding error. Other detected joint additive recession directions
affecting calibration also stop this route; passing these checks is not
a general finite-MLE certificate.
Adding an informative interior Person anchor can restore a finite ordinary solution, but does not by itself establish native calibration agreement. In matched RSM/PCM examples with this support, FACETS retained the fixed extreme Person’s responses. Fair scores and conditional Rater-by-Task bias calculations agreed with independent calculations using the native reported calibration. The main estimates still differed from ordinary JML: free-Person score residuals remained, and the maximum-score examples reached the main iteration limit. These results separate conditional reporting agreement from calibration agreement; they do not identify every internal cause of the native behavior.
For ordinary additive RSM/PCM JML,
fair_average_table(..., totalscore = FALSE) now retains
finite direct anchors under both xtreme_method conventions.
An anchored element’s all-minimum/all-maximum responses do not
themselves make it an unanchored infinite estimate. Other unanchored
extreme elements still trigger exclusion. The PCM fair score and its
conditional plot derivative use the same retained scale mixture.
Recreate affected older tables and plots from the saved fit and matching
diagnostics; no calibration refit is required.
estimate_bias() also retains directly fixed finite
anchors in ordinary additive RSM/PCM JML, including with the default
xtreme = 0. Person-by-Rater cells should not disappear
merely because that fixed Person’s observed scores are all minimum or
maximum. Without extrapolation, a boundary cell keeps its bounded point
and unavailable screening SE/tail area. Recreate affected bias tables
and collections from the saved fit and matching diagnostics.
The FACETS Xtreme
specification has separate main-effect and bias corrections. To
match its usual bias correction use
estimate_bias(..., xtreme = .5); .3 is the
usual main-effect correction. Executed Person-by-Rater checks agree with
the conditional calculation on matched main calibrations. The correction
can even change the sign relative to the observed departure: an all-zero
cell with expected total below 0.5 needs a positive shift to attain the
amended total 0.5. Read PrimaryBias,
ExtremeAdjustment and Obs-Exp Average
together. This remains an extrapolated screen for expert review, not a
fairness finding.
For an executable example, each row of the bundled ratings is a Person’s score from one Rater on one Criterion. Treat the R01 anchor below as a supplied external value for illustration, not an independently validated calibration:
ratings <- load_mfrmr_data("example_core")
rater_anchor <- data.frame(Facet = "Rater", Level = "R01", Anchor = 0.7)
anchored_fit <- fit_mfrm(
ratings, person = "Person", facets = c("Rater", "Criterion"), score = "Score",
method = "JML", anchors = rater_anchor, centering_scope = "anchor_origin"
)
anchored_fit$config$anchor_review$facet_summaryThe table’s Centered and OriginBasis
columns show which origin constraints were applied. This leaves Person
noncentered, fixes R01, frees the other Rater locations from a zero-sum
requirement, and centers Criterion. Existing "facet"
(default) and "remainder" conventions remain available and
impose different constraints with partial anchors. Refitting is required
to change conventions. All options condition on supplied anchors; they
do not propagate uncertainty in previously estimated anchor values.
For a group origin, translate the native group total before fitting.
In FACETS Labels= ...,G, contributions 0.2 and 1.0 for two
members fix their sum at 1.2. mfrmr uses the mean 0.6, repeated for both
rows:
ratings <- load_mfrmr_data("example_core")
group <- data.frame(
Facet = "Rater", Level = c("R01", "R02"), Group = "panel",
GroupValue = 0.6
)
group_fit <- fit_mfrm(
ratings, person = "Person", facets = c("Rater", "Criterion"), score = "Score",
method = "JML", group_anchors = group, centering_scope = "anchor_origin",
anchor_policy = "error"
)
group_fit$config$anchor_review$facet_summary
subset(group_fit$facets$others, Facet == "Rater")The first table identifies the Rater origin as
group_anchors. In the second, R01 and R02 average 0.6 but
their individual measures are estimated; the other Raters need not sum
to zero. The supplied group mean is a substantive assumption, and its
uncertainty is not propagated. Unequal GroupValue rows are
conflicting mean targets, not contributions to be averaged by the
normalizer.
FACETS group codes
also need translation: group 0 specifies direct anchors, so use
anchors, not Group = "0". A missing native
contribution does not participate in the group anchor. The native
X option excludes extreme elements; mfrmr retains its
declared members and does not reproduce that option automatically.
Executed interior RSM/PCM examples agree closely when the group only selects an origin. Adding a second, restrictive group exposed a smaller but real difference: FACETS 4.5.0 preserved both targets, yet a constraint-preserving change increased the ordinary likelihood. mfrmr therefore retains constrained maximum likelihood rather than emulating that numerical result. Matching group means does not establish identical estimates, SEs or interval coverage. General group-anchor extreme extrapolation remains unsupported.
review_mfrm_anchors() normalizes and reports on the
constraint block before the fit runs, surfacing duplicate/direct-group
overlap and local support-count issues. It does not evaluate assignment
connectedness, source-fit readiness, or cross-run element invariance;
use the design-network route and substantive identity evidence
separately.
For FACETS Table 13 cell-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.
screens <- estimate_all_bias(fit, diagnostics = diag)
summary(screens) # Pair counts, availability and magnitude
head(summary(screens)$cells) # Signed effects, SEs and observed counts
plot(screens) # All retained cells grouped by pair
plot(screens, pair = "Rater x Criterion") # Individual heatmapThese are exploratory conditional screens: baseline calibration and
Person uncertainty are held fixed. ScreenPositive counts
available statistics with absolute value at least two; it is
NA when none is available. Review errors, unavailable cells
and observed counts before interpreting zero flags. The batch does not
supply collection-wide multiplicity control, and a flagged cell alone
does not establish unfairness.
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")
review$decision
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")Read review$decision before using the FACETS-organized
tables. It reports the same stored mfrmr readiness decision shown by
print(fit); the facets profile changes the
organization of the review, not the estimator and not the evidence
threshold. FormalInference = "No" withholds the
corresponding formal inferential claim even when a familiar table or
plot is available. It does not turn every descriptive result into an
unusable result: report a valid descriptive target with its limitation,
and identify which comparisons or uncertainty statements are
unavailable.
plot() 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 G group anchors constrain sums over specified
elements. mfrmr’s GroupValue is the mean target for the
group. For example, the following schematic input constrains the mean of
two Rater elements to zero; it does not define response groups for a DFF
analysis:
group_anchors <- data.frame(
Facet = "Rater",
Level = c("R1", "R2"),
Group = c("PanelA", "PanelA"),
GroupValue = c(0.0, 0.0),
stringsAsFactors = FALSE
)
fit_g <- fit_mfrm(..., group_anchors = group_anchors, anchor_policy = "error")
diag_g <- diagnose_mfrm(fit_g)
dff <- analyze_dff(fit_g, diag_g, facet = "Criterion",
group = "FirstLanguage", data = ratings_with_language,
method = "refit")Replace ... with the fitting arguments for your data and
supply ratings_with_language containing the response-group
column FirstLanguage. Use diagnostics from
fit_g, not from a different fit. Assigning the same element
to two different groups is not this mean-constraint construction. A
group-anchor target is an external mean constraint, not an empirical
link. Its use requires a defensible equal-mean or known-target
assumption for the declared elements and does not connect otherwise
unobserved rating subsets.
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
GPCM the score-side bundle is intentionally restricted; see
?gpcm_capability_matrix and the
mfrmr-gpcm-scope vignette for the documented
limitation.
For a Person comparison on the same scale exposure,
supply reference_plan to fair_average_table().
Its reference_scores component uses each Person’s primary
estimate with the actual fitted locations and scale profiles in that one
weighted plan. This is a distinct expected-score target: PCM FairM/FairZ
still retain each Person’s administered scale mixture. Score direction
remains defined by the rubric; a higher standardized expected score is
not automatically a judgment of better performance or fairness.
confint(fair, parm = ..., nsim = ..., seed = ...)
provides an experimental ordinary-JML refit route for common-plan scores
and named paired contrasts. When anchors were estimated from the same or
overlapping samples, supply their anchor_source, a
generating fit on the union of response events where needed, and
explicit calibration/scoring row maps. The maps assert which
observations are actually shared: equal labels alone do not establish
event identity. Every replication re-estimates calibration and anchors
before scoring; shared responses are generated once. Without the source
and correspondence, estimated- anchor intervals are unavailable.
anchor_uncertainty = "fixed" is an explicit conditional
alternative, not a substitute for propagating estimated anchors.
Explicit generator_method = "jeffreys" offers an
experimental refit option when extreme Person estimates prevent an
ordinary generating model. It fits a canonical information-penalized
model on the generating data, then simulates shared events once and
reruns the ordinary calibration/anchor/scoring estimator. The original
ordinary-JML points remain unchanged; extreme Persons retain limiting
expected scores. Inspect attr(result, "generating_model")
and attr(result, "generating_target") to distinguish the
generator from the reported estimate. Declare the rubric and retain its
full coding when fitting. This option is not available for delta or
bounded intervals, and it does not resolve infinite estimated anchors or
unqualified structural calibration.
A finite generator alone does not justify nominal coverage or
score-bias reduction. The bias correction for canonical parameters does
not automatically transfer to expected scores: even the binomial
probability (S + .5)/(n + 1) has bias
(.5 - p)/(n + 1). The option is separate from FACETS Xtreme
and mfrmr’s corrected-GPCM estimator; it leaves
CIEligible = FALSE.
An alternative is to select jml_penalty = "jeffreys"
with method = "JML" in every original
calibration, scoring and union fit. This changes the reported points as
well as every replicate fit. The separate mfrm_jeffreys_fit
result supplies Person, facet and step points and numerical checks; it
does not inherit ordinary SEs or FACETS diagnostics. For its common-plan
scores, call
fair_average_table(fit, reference_plan = plan). The
existing confint() interface propagates estimated anchors
and shared events using the same penalized estimator throughout. Its
generating method defaults to Jeffreys, using the supplied penalized
union fit. Mixing ordinary and penalized fits across stages is refused.
With method = "delta", the analytic derivative follows the
penalized equations, including the change in the penalty when estimated
anchors change. Shared response events contribute to both stages before
computing covariance. This is a local model-based approximation, not
inverse penalized curvature or a coverage guarantee. Inspect
summary(fit)$checks and
attr(result, "settings")$estimator to record which
procedure was used. Declared empty categories are retained; unidentified
designs and numerical failures are still refused. Finite-sample score
bias, coverage and global optimization remain unqualified. This option
is separate from FACETS Xtreme and corrected GPCM, and is not a
FACETS-compatible default.
There is a concrete reason to retain the experimental label. With six
binary responses and true success probability 0.5, exact enumeration
gives 78.125% coverage for nominal 95% Jeffreys delta intervals. At
probability 0.25, it is 78.4424%. The local variance formula is correct;
the plug-in normal interval still fails to achieve its nominal coverage.
More Persons do not necessarily provide more responses for the
particular Person being scored. Use Available to check
whether a result was computed, and CIEligible and the saved
notes to assess its inferential status. Basic refit intervals also have
counterexamples: with six responses and true probability 0.1, exact
refit quantiles give coverage 45.2709%. An all-zero sample’s upper basic
limit equals the fitted score 0.5/7, below the true probability. Even
infinitely many refits do not fix this; Monte Carlo precision and
sampling coverage are different requirements. The conservative bounded
method retains its distinct assumptions and can be wide in sparse
designs.
Read the interval table’s Status,
Available, Unresolved and
ExpectedTailDraws together. Numerical availability does not
qualify coverage: the initial method is a pointwise fitted-model
approximation, with no correction for JML incidental-parameter bias or
guarantee under misspecification. Unresolved trials stay in the
denominator and can make tail limits unavailable. The four
LowerMCLower/LowerMCUpper and
UpperMCLower/UpperMCUpper columns separately
enclose the Monte Carlo error of the two endpoints, at
mc_level (default .95).
attr(result, "monte_carlo") retains the underlying binomial
ranks. Infinite enclosures expose insufficient draws or unresolved
refits; MCFinite = TRUE means finite, not necessarily
precise enough. These diagnostics cover both endpoints for one fixed
target under a fixed generating model and independent replications. They
do not guarantee coverage across targets, adaptive reruns, or repeated
samples of the original data. The plot still shows the empirical
interval; its saved payload retains the Monte Carlo diagnostic for
inspection. summary() and plot() reuse the
saved result, and saveRDS() preserves its replications,
checks and provenance. These intervals concern expected scores, not
future observed ratings; they do not certify unfairness. The method’s
help contains an executable example and the supported estimation/design
restrictions.
confint(fair, parm = ..., method = "delta") evaluates a
deterministic local approximation through the same estimator. Supply the
same calibration fit, union fit and event maps when anchors are
estimated. Omit nsim and seed. The result adds
SE, Reason and
attr(result, "covariance"); its
covariance_components attribute separates direct scoring,
propagation through calibration and the signed shared-event cross term.
These terms retain the covariance needed for paired differences; a
marginal anchor SE cannot replace them. The count columns for
simulations are NA because this method does not run
replications.
Delta limits use a local normal approximation centered on the
observed estimate. They require finite estimates and positive
information, and do not correct JML bias or establish coverage. Missing
bounds retain their reasons; bounds outside the score support are not
clipped. Compare the numerical approximation and availability under the
intended design before using either method for decisions. The help for
confint.mfrm_fair_average gives the derivative, uncertainty
basis and references. These procedures require native fitted models;
descriptive FACETS-result imports do not provide the source model or
joint uncertainty.
confint(fair, parm = ..., method = "bounded") is a
conservative alternative for the same true common-plan score or
contrast. It uses scoring responses directly, so extreme Person
estimates and the absence of an estimated-anchor covariance do not
require a fitted generating model. Omit calibration/generator arguments
and simulation controls for this method. Its finite-sample probability
bound requires independent bounded responses, a fixed exogenous
assignment, plan and contrast, and stable expected scores within each
Person-plan cell. It is pointwise and does not justify selecting
comparisons after seeing scores or claiming nominal coverage conditional
on successful fitting. Declare both rating_min and
rating_max from the rubric when fitting, and retain the
full score coding with category_policy = "preserve".
Observed sample extrema and internally collapsed categories are not
accepted as known support. The interval result saves this basis in
attr(result, "settings")$score_support. A retained empty
category that prevents fitting is still a failure; changing the rubric
to obtain an interval changes the inferential target.
The tradeoff is width: every unobserved plan cell keeps its full
score range instead of borrowing a model prediction. Inspect
Informative and attr(result, "support"); an
available full-range bound is explicitly uninformative.
Estimate retains the JML point, while
DesignEstimate is a separate unbiased weighted mean only
with complete plan support. The interval can be asymmetric around or
exclude the JML point. It is not a bias correction, a FACETS interval
convention, or a solution to dependent ratings. Failure to construct the
prerequisite fitted result remains an end-to-end availability failure,
even though the concentration inequality itself needs no fitted
model.
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() 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 7 fair-average
review is needed.plot(fit, type = "wright") or plot() 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.