Respondents with no responses at all
(all-NA rows) no longer crash the functions that fit a CML
model on data retaining missing values.
psychotools::pcmodel() errors on all-NA rows with an opaque
“invalid argument type” (and psychotools::raschmodel()
segfaults), so such rows are now dropped up front — with the standard
“N respondent(s) with no responses dropped.” message — in
RMlocdepQ3Cutoff(), RMitemInfit(),
RMitemRestscore(), RMitemRestscoreBoot(),
RMreliability(), and the observed-data overlays of
RMlocdepQ3Plot() and RMitemInfitPlot().
RMdifLR() now drops such rows too (jointly with
dif_var) instead of failing with
eRm::LRtest()’s error. Functions that already used complete
cases or called .drop_empty_respondents() are
unaffected.
RMlocdepQ3Cutoff()’s sample_n now
counts the respondents actually used (all-NA rows excluded, incomplete
responses still retained) and sample_n_total the raw input
rows, matching RMlocdepQ3() and the other
*Cutoff() objects; previously the two were documented as
always equal. Captions in the affected functions keep reporting the raw
total in the n = X of Y respondents form.
RMdimMartinLof() /
RMdimMartinLofResiduals(): corrected the category weights
in the Monte Carlo null sampler and the expected-count
computation (present in 1.0.0). The item parameters were passed
to psychotools::elementary_symmetric_functions() with the
wrong sign convention (it weights categories by exp(-par)),
so the gamma functions used sign-inverted weights while the sampler’s
numerator used the correct ones. Consequences of the bug: simulated null
datasets did not follow the fitted model, the Monte Carlo null
distribution (and hence the p-value) depended systematically on the
column order of the data, and the residual table’s expected
counts were wrong. The fixed sampler reproduces the exact conditional
pattern distribution (verified against brute-force enumeration), and
expected counts match enumeration exactly. Martin-Löf p-values
and residuals change relative to 1.0.0 — typically the
corrected null distribution sits lower, so rejections become somewhat
clearer. In addition, items are now processed in a fixed (alphabetical)
internal order, so the same seed reproduces the same p-value regardless
of how the data’s columns are arranged.
RMreliability() is now fully reproducible with the
same seed: the RMU estimate previously varied slightly
between identical calls because mirt’s Metropolis-Hastings
plausible-value sampler leaves the R random-number stream in a
nondeterministic state (the draws themselves are reproducible), which
perturbed the RMU split-half column assignments downstream. The function
now re-seeds before the RMU iterations.
RMdimMartinLof() now returns
p_value_floor (1 / (actual_iterations + 1)),
the smallest attainable Monte Carlo p-value; the documentation explains
that a p-value equal to the floor means no simulated statistic reached
the observed one and should be read as “p < floor” (increase
iterations for finer resolution). The vignette’s Martin-Löf
example now sets a seed and discusses this.
RMdifTree() gains output = "list",
returning both the tidy effect-size table ($table) and the
augmented tree object ($tree) from a single fit (used by
the jamovi module).
RMpersonFit() gains output = "list",
returning both the per-person data.frame ($fit) and the
named list of person-fit maps ($plots) from a single
computation — avoiding a second resampling run when both views are
needed (used by the jamovi module).
output = "dataframe" now returns unrounded
values across the package; rounding is a presentation concern
and now happens only when rendering the kable (whose displayed precision
is unchanged). Affected functions: RMitemInfit(),
RMitemInfitMI(), RMitemRestscore(),
RMitemRestscoreBoot(), RMlocdepQ3() (the
$pairs table), RMdifGamma(),
RMlocdepGamma(), RMdimResidualPCA(),
RMdimCFA() (both $fit and
$loadings), RMreliability(),
RMdifLR(), RMdifTree() (including the
stability summary attribute), RMdimMartinLof() (the
wle_correlation element),
RMdimMartinLofResiduals(),
RMpersonParameters() (dataframe and file/CSV output),
RMpersonFit(), and RMitemParameters()
(dataframe and file/CSV output; previously rounded to 4 decimals, which
also made the wide format’s mean location differ from the
mean of its rounded threshold columns in the 5th decimal).
RMscoreSE() already followed this convention.
Consequently, Flagged labels and sorting are now
always computed on the exact (unrounded) values. Items or pairs sitting
exactly on a rounded boundary could in principle change flag relative to
earlier releases; displayed tables are otherwise identical.
Deliberately unchanged: the infit simulation workers still round the per-iteration statistics to 3 decimals before the cutoff computation, so simulation-based expected ranges reproduce earlier releases exactly.
Minor layout changes for RMtargeting() regarding
number of bins if not set by user. Earlier it was sum score + 1, now it
is sum score divided by 2. RMitemICCPlot() gets slightly
larger points and thicker error bars.
RMitemICCPlot() gains two grouping methods for the
observed means, alongside the existing quantile grouping
(method = "cut" is now a legacy alias for
method = "quantile"): method = "width" for
equal-width intervals on the total-score scale, and
method = "manual" with the new score_breaks
argument – the total scores at which a new group starts (the concept of
RASCHplot’s lower.groups, without the leading zero). The
documentation of the grouping rules and of the error_band
(the model-implied interval for the observed mean per total score) was
substantially expanded.RMplotTile() gains a text_size argument
for the cell labels (default 4, matching RMitemCatProb()),
and cells with zero responses are now visually
distinct: they are taken off the colour scale and shown
unfilled with a light grey outline (zero_fill = "white",
set to NULL for the previous behaviour), so the absence of
data reads as absence rather than as the darkest end of the fill scale,
where n = 0 was nearly indistinguishable from
n = 1. The caption notes the convention when empty cells
are present.RMlocdepGamma()’s output = "dataframe"
tables now include the se, lower, and
upper (95% Wald CI) columns for each pair, matching
RMdifGamma(); the formatted kable output is unchanged.A large consolidation release. The headline change is that the whole
package now runs on a single estimation engine —
conditional maximum likelihood (CML) item parameters via
psychotools and Warm’s weighted-likelihood (WLE) person
locations — replacing the previous mix of eRm (MLE) and
mirt (MML/EAP). On top of that: new CFA loading
diagnostics, three new functions for person+item parameters and person
fit, bootstrap p-values with multiplicity correction, and a round of
naming/output consistency fixes. After this release eRm is
used only by RMdifLR() (Andersen’s LR test) and
mirt only for the RMU plausible values
(RMitemInfitPlot()’s observed-fit overlay moved from an
eRm fit to psychotools::pcmodel(), matching
RMitemInfitCutoff(); values agree to ~1e-6). Accordingly,
eRm has moved from Imports to Suggests:
RMdifLR() errors with an install hint when it is
absent.
Many items below shift reported numbers slightly: the underlying statistics are unchanged, only the estimation engine (WLE locations are finite at extreme scores, so extreme-score cases are now retained rather than dropped).
RMitemRestscore(), RMitemInfit(),
RMitemCatProb(), RMitemHierarchy(),
RMtargeting() — moved to CML (psychotools) +
WLE. The conditional iarm statistics are engine-invariant;
only minor things move on the common grand-mean-zero scale
(Relative_location via the WLE person mean; threshold SEs
~few %; polytomous ICC curve position; the targeting person
distribution). RMdifLR() deliberately stays on
eRm::LRtest()..rasch_fit_cml() behind RMitemParameters(),
RMpersonParameters(), RMscoreSE() now fits by
CML via psychotools. Locations, person estimates and score
SEs are unchanged (match eRm to ~5e-5); only
RMitemParameters()’s threshold SEs shift slightly
(psychotools vcov vs the eRm delta method, ~few %).RMscoreSE() — the WLE method now
reports the information-based SE 1/sqrt(I(theta)) (matching
RMpersonParameters(), catR, TAM);
point estimates unchanged, SEs differ (larger) at the score extremes,
and the WLE solver/centring is now shared with
RMpersonParameters().RMreliability() — empirical
reliability is replaced by a native marginal
reliability (Green 1984; the “Empirical” row is now
“Marginal”), While mirt::marginal_rxx() uses
N(0,1), this integrates over the estimated latent variance,
so it is correct on the Rasch logit scale; and the PSI
is now the WLE-based separation reliability
(1 - mean(SEM^2)/Var(theta), excluding extreme scorers),
replacing eRm::SepRel() + mirt. The bootstrap
is now fully native (no mirt per resample). PSI can differ
noticeably for scales with many extreme scorers; alpha and RMU are
unchanged.RMlocdepQ3()/RMlocdepQ3Cutoff(),
RMitemInfitCutoff(),
RMitemInfitMI()/RMitemInfitCutoffMI(),
RMitemRestscoreBoot(),
RMdimResidualPCA()/RMdimResidualPCACutoff(),
RMdimCFACutoff(), RMdimMartinLof(),
RMdifGammaCutoff(), RMlocdepGammaCutoff(). The
eRm-based internal extract_item_thresholds() helper is
removed. Conditional / scale-invariant statistics (infit/outfit,
item-restscore classification, the Martin-Löf Monte-Carlo p-value,
pooled MI infit MSQ/SE) are unchanged; residual-based and simulated
quantities shift slightly — Q3 values/cut-offs/flags (the statistic is
unchanged; observed-vs-old-MML correlation is typically >0.95), PCA
eigenvalues / variance partition / cut-off, and the gamma cut-offs.RMlocdepQ3()/RMlocdepQ3Cutoff() keep the
previous engine available via estimator = "MML" (default
"CML"); the estimator is stored in the cutoff object and
reused by RMlocdepQ3()/RMlocdepQ3Plot() (a
mismatch is overridden with a warning). RMitemInfitMI()’s
pooled-SE caveat (Müller 2020) is now documented.RMpersonFit() — per-respondent
conditional infit/outfit MSQ and the standardized log-likelihood
lz, computed per response pattern (handles partial
missingness, no biased person estimate in the residual). Significance is
by Monte-Carlo resampling under the fitted model, not the unreliable
asymptotic null (Sinharay 2016; Müller 2020). Output as table,
data.frame, or a named list of person-fit maps; zstd = TRUE
adds the Wilson-Hilferty transform (comparability only, not for
inference); flag = "underfit" restricts flagging to the
validity-relevant direction.RMitemParameters() — item difficulty
(dichotomous) or Andrich-threshold (polytomous) parameters in long/wide
format, with optional SEs and Wald CIs.RMpersonParameters() — per-respondent
theta and SEM computed on each response pattern (handles partial
missingness), via Warm’s WLE (default) or EAP under a normal prior (SD
estimated by marginal ML unless fixed).RMitemParameters() and
RMpersonParameters() support output = "file"
to write the result table to a CSV at filename (the
data.frame is also returned invisibly).CFA now also reports per-item standardized factor loadings (observed vs a simulated expected range), restructured to match the other simulation tools:
RMdimCFACutoff() is now simulate-only
— returns the simulation object (null distributions + cutoffs for fit
indices and loadings); it no longer computes the observed fit,
and output = "kable" errors with a pointer to
RMdimCFA(). (Breaking.)RMdimCFA() (new) takes data + a
required cutoff object and returns a list of two tables,
$fit (CFI/RMSEA/SRMR) and $loadings (observed
loading vs the two-sided expected range), as kables (default) or
data.frames.RMdimCFAPlot(cutoff_res, data) now returns a
list of two ggplots ($loadings, in the
RMitemInfitCutoffPlot() style; and $fit, the
faceted fit-index distributions) and requires data.
(Breaking: previously a single ggplot.)Six simulation-based diagnostics gain optional bootstrap p-values
computed against their simulated null distributions
(p_value = TRUE; the default FALSE leaves
existing output unchanged). Shared mechanics: each statistic is
studentised by its bootstrap mean/SD; marginal Monte-Carlo p-values have
floor 1/(B+1); correction offers
Westfall-Young studentised-max step-down FWER (default),
Benjamini-Hochberg or Benjamini-Yekutieli FDR, or "none";
Flagged then reflects padj < alpha while
the simulated effect-size bands stay in the tables. The full
*Cutoff() object is required, and >= 1000 cutoff
iterations are recommended (warning below that). (Ferreira 2024;
Westfall & Young 1993.) Per function:
RMdifGamma(): two-sided per item. The asymptotic
BH-adjusted p-value and star columns from iarm are dropped
in this mode (one p-value family per table); p_gamma /
padj_gamma replace them.RMdimCFA(): one-sided in the unfavourable direction for
CFI / RMSEA / SRMR, two-sided for the per-item loadings, corrected as
two separate families.RMdimResidualPCA(): a single one-sided test of the
first-contrast eigenvalue, so no multiplicity correction is
involved.RMitemInfit(): two-sided per item.RMlocdepGamma(): one-sided per pair for excess positive
LD (matching RMlocdepQ3()), computed once per pair in the
canonical direction (rest score = total − Item2, the simulated
direction) and repeated in the direction-2 table; correction runs over
the full pair family before any n_pairs display filter; the
iarm BH columns are dropped as in
RMdifGamma().RMlocdepQ3(): one-sided per pair, folded into the new
per-pair $pairs table returned alongside
$matrix (observed Q3 vs simulated band, directional flag,
sorted by departure from the per-pair median, optional
n_pairs cap).RMitemInfit(), RMlocdepQ3(), and the newly
extended functions share a “Multiple comparisons” help section.
n = X of Y respondents (<policy>),
where of Y appears only when respondents were excluded and
the policy note (complete cases /
incomplete responses retained /
missing values imputed) only when the input contained
missing values — complete data reads simply
n = X respondents. Terminology is “respondents” throughout
(previously a mix of “persons” / “complete cases”). Sample size is newly
reported by RMitemParameters(),
RMpersonParameters(), RMitemHierarchy(),
RMitemCatProb(), RMscoreSE(),
RMlocdepQ3(), RMdimResidualPCA(),
RMpersonFit()’s kable, and the descriptive plots
(RMplotBar(), RMplotStackedbar(),
RMplotTile()); all other captions are reworded to the
common form. The bootstrap-null plots (RMitemInfitPlot(),
RMdifGammaPlot(), RMlocdepGammaPlot(),
RMlocdepQ3Plot(), RMdimCFAPlot()) report the
simulation sample the same way, suffixed per dataset; their
*Cutoff() objects store sample_n_total /
sample_has_na, with a graceful fallback for cutoff objects
from older versions. Respondents with no responses (all-NA rows) are
dropped with a one-time message rather than triggering a CML fitting
error, and RMplotTile() likewise messages when rows with
NA in group are dropped (previously silent;
item-level NAs are retained in the descriptive plots).RMdifGammaCutoff() no longer prints an
iarm::partgam_DIF() result table on every iteration in
sequential (parallel = FALSE) runs; the silencing sink is
now also restored safely on iteration failure (hardened in
RMlocdepGammaCutoff() too).RMdifLR() captions now report the Andersen LR p-value
as a plain number (exact to three decimals, p < 0.001
below that) instead of the format.pval() scientific
notation (<1e-04), and the test statistic is shown as χ²
instead of chi^2.RMdimResidualPCA() plot output is now
output = "ggplot" ("loadings" kept as a
backward-compatible alias); RMtargeting()
output = "figure" → "patchwork" (matching
RMitemICCPlot()); RMitemRestscore()
p.adj → p_adj; RMitemInfitPlot()
output → statistic.RMitemInfitCutoffPlot() renamed to
RMitemInfitPlot(), matching the
<base>Plot form of the other bootstrap-cutoff plot
functions (RMdifGammaPlot(),
RMlocdepGammaPlot(), RMlocdepQ3Plot(),
RMdimCFAPlot()). Because the old name shipped in the 0.8.0
CRAN release, it is kept as a deprecated alias that
warns and forwards (unlike the 0.8.0 renames, which dropped old names
outright). Separately, RMdimCFAPlot()’s first argument
cutoff_res was renamed to simfit to match the
other plot functions (no alias).RMdifLR() now defaults to output = "kable"
(was "ggplot"), matching every other function that offers
both a kable and a ggplot output
(RMscoreSE(), RMdimMartinLof(),
RMpersonFit(), RMpersonParameters(),
RMdimResidualPCA()). Pass output = "ggplot"
for the previous default.Flagged column now labels misfit
direction ("overfit" /
"underfit" / "") instead of logical TRUE/FALSE
in RMitemInfit() / RMitemInfitMI() (column
type changes from logical to character). RMitemRestscore()
gains a Flagged column and drops the redundant
significance-star and Location columns (trimmed headers +
explanatory caption). Note the value direction differs: a high
infit is underfit, a high restscore correlation is
overfit.RMitemInfitMI() and RMitemInfitCutoffMI()
now accept mids objects whose items were imputed as ordered
factors (as required by mice’s polr method): the completed
data are coerced back to numeric responses internally, rather than
erroring on the factor columns.RMitemInfitCutoff() and RMlocdepQ3Cutoff()
gain an experimental dgp argument — "resample"
(default; resample WLE locations and simulate, a marginal null) vs
"conditional" (simulate each pattern from the exact Rasch
conditional given the observed total score, a matched conditional null)
— stored in the result. See dev/q3_dgp_comparison.R /
dev/infit_dgp_comparison.R.$matrix /
$pairs structure. RMlocdepQ3Plot() returns a
list of two plots: $pairs (the per-pair
simulated-vs-observed dot-interval, previously the single return value)
and $matrix (a lower-triangle diverging-RdYlBu Q3 tile
heatmap with above-cutoff pairs outlined, adapted from
RASCHplot::ggQ3star(); needs data, else
NULL).RMitemICCPlot() is reimplemented on the CML engine,
replacing the iarm::ICCplot() wrapper. The conditional item
curve and its variance now come from psychotools CML
thresholds + the exact conditional distribution given the total score.
It draws confidence intervals on the observed
class-interval means (ci, default on) and an optional model
band (error_band); in DIF mode it shows per-group CIs and
annotates each panel with the partial-gamma DIF
magnitude (iarm::partgam_DIF, as in
RMdifGamma()), with the full table attached as
attr(., "dif_gamma"). New arguments ci,
error_band, conf_level, min_n
(per-cell floor, 8), items; method /
class_intervals / dif_var /
output are unchanged. The conditional-ICC approach follows
Buchardt, Christensen & Jensen (2023) and their
RASCHplot package.RMlocdepGamma(): corrected the $direction2
caption / @return wording to “total - Item2” (with a note
that direction 2 lists pairs in reverse order); computations unchanged
(labelling fix).RMdifTree(): fixed a “variable lengths differ” error
when a single covariate was passed by index or expression
(e.g. covariates = phq9[, 10]). The derived non-syntactic
column name is now matched as a literal column rather than re-evaluated
as an R expression against the original (pre-NA-drop) data.RMdifTree(stability = TRUE) no longer silences the
console in front-ends (e.g. RStudio) that redirect the message stream.
The internal stderr capture used to muffle resample-fit noise reset the
message sink to the default, clobbering the front-end’s sink; it now
only redirects when no foreign message sink is active.RMitemRestscore(p_adj = "none") now returns the
unadjusted p-values instead of NA with a “NAs introduced by
coercion” warning. With no adjustment
iarm::item_restscore() omits the adjusted-p column, so the
p-value is now selected by name rather than by a fixed column position
(which had picked up the significance-stars column). The table header
reads “p-value” in this case.RM* function that returns a ggplot
now applies three shared internal theme helpers:
er2_axis_margins() — extra breathing room around the x
and y axis titles.er2_plot_caption() — left-aligned 9 pt plot caption.
When the optional ggtext package is installed (new in
Suggests), the caption renders via
ggtext::element_markdown() so the APA-conventional italic
“Note.” prefix can sit alongside roman body text. Without
ggtext, it falls back to a plain
element_text(face = "italic") and a plain “Note.” prefix —
no markdown asterisks ever leak through to the rendered text.er2_caption() — builds the caption string with the
“Note.” prefix and wraps long captions at 90 characters via
strwrap() so they no longer run off the right edge of the
plot. The body text is wrapped first then prefixed, so the prefix is
never broken by a line break.@noRd) and not
exported.RMitemCatProb() plots model-implied
category-response probability curves per item, similar to
eRm::plotICC() or mirt trace plots but with a
ggplot2 / viridis output. Each item gets its own facet
panel; one curve per response category is coloured from low to high
using a continuous viridis palette. Polytomous items are fit with
eRm::PCM(); dichotomous items fall back to
eRm::RM() (recovering the standard two-category logistic
ICC). Optional descriptive item_labels and
category_labels make the output report-ready.
label_curves = "path" mode
(requires the optional geomtextpath package, in Suggests)
writes each category’s label along its own curve in the classic
IRT trace-plot style. Single-item only — pass the full multi-item
dataset and use the item argument to choose which item’s
curves to plot. The model is still fit on all items (CML threshold
estimation needs the full dataset); only the rendering is filtered. Each
category’s label is positioned at that curve’s modal theta (the peak of
its bell for middle categories; the relevant edge for the monotone
extreme categories), clamped a small margin in from the plot edges to
prevent clipping.This release renames 22 exported functions under a
consistent domain-prefix → method → variant-suffix scheme so
that autocompletion on a prefix (RMdif,
RMlocdep, RMitem, RMdim,
RMplot) surfaces every related function. No semantic
changes; only names.
A complete mapping is on the new ?easyRasch2-renaming
help page. The short version:
| Domain | Prefix | Examples |
|---|---|---|
| DIF | RMdif |
RMdifGamma(), RMdifGammaCutoff(),
RMdifGammaPlot(), RMdifLR(),
RMdifTree() |
| Local dependence | RMlocdep |
RMlocdepQ3(), RMlocdepQ3Cutoff(),
RMlocdepQ3Plot(), RMlocdepGamma(),
RMlocdepGammaCutoff(),
RMlocdepGammaPlot() |
| Item statistics | RMitem |
RMitemInfit(), RMitemInfitCutoff(),
RMitemInfitCutoffPlot(), RMitemInfitMI(),
RMitemInfitCutoffMI(), RMitemRestscore(),
RMitemRestscoreBoot(), RMitemICCPlot(),
RMitemHierarchy() |
| Dimensionality | RMdim |
RMdimResidualPCA(),
RMdimResidualPCACutoff(), RMdimCFACutoff(),
RMdimCFAPlot(), RMdimMartinLof(),
RMdimMartinLofResiduals() |
| Descriptive plot | RMplot |
RMplotTile(), RMplotBar(),
RMplotStackedbar() |
Unchanged: RMreliability(),
RMUreliability(), RMtargeting(),
RMscoreSE().
Breaking change. No deprecation aliases are shipped
— existing scripts will need a search-and-replace. See
?easyRasch2-renaming for the full table.
RMlocdepQ3plot() for visualising
per-pair simulated Q3 distributions against observed Q3 values,
mirroring the design of RMpgLDplot() and
RMpgDIFplot(). Supports items and
n_pairs filters; with data supplied, ranks
n_pairs by
|observed Q3 - median(simulated Q3 per pair)|.RMlocdepQ3cutoff() now retains per-pair iteration-level
data: the returned list gains pair_results,
pair_cutoffs, item_names,
cutoff_method, and hdci_width. Existing scalar
outputs (suggested_cutoff etc.) are unchanged. New
arguments cutoff_method ("hdci" /
"quantile") and hdci_width (default
0.99) control how per-pair credible intervals are
computed.RMlocdepQ3() can now be called with the full list
returned by RMlocdepQ3cutoff() (it auto-extracts
$suggested_cutoff), matching the partial-gamma family
convention. Numeric scalar still works.RMpartgamLD() and RMpgLDplot() gain an
n_pairs argument to keep only the top-N pairs by
|gamma| (LD) or by |observed - median(sim)|
deviation (plot).RMpartgamLD(), RMpartgamDIF(), and
RMitemrestscore() now use consistent column headers:
Adj. p-value (BH) and a new p-value sign.
star-string column. RMitemrestscore()’s former
Absolute_difference column is now a signed
Difference (observed − expected), so over- and underfit are
visually distinguishable at a glance.RMbarplot() and
RMstackedbarplot() join
RMtileplot() for easy visualization of item response data
distributions.RMciccPlot() for conditional item
characteristic curves plot, also includes DIF analysis for categorical
DIF variables.RMitemHierarchy(), which outputs a
plot illustrating the item hierarchy with item thresholds and confidence
intervals.RMcfaCutoff() to only use .scaled metrics for
RMSEA and CFI, for stability. See documentation for more details.RMmartinLof() with dichotomous items.RMitemHierarchy() making option
item_labels work as intended.RMcfaCutoff() for testing
unidimensionality against simulation-based cutoff values for model fit
metrics.
RMcfaPlot() shows figure with
distribution of simulation results and observed model fit values.RMdifTree() for testing DIF with
continuous variables, such as age in years, as well as combinations of
DIF variables (DIF interactions).
stablelearner, as recommended by
Henninger et al.
?RMdifTree) for more details:
RMdifLR() for testing DIF of
categorical variables using Andersens’s Likelihood Ratio test as
implemented in package eRmRMtileplot().
group faceting, which is useful for
DIF-analyses.RMmartinLof() based on Christensen &
Kreiner (2007, doi: 10.1177/0146621605286204), for both dichotomous and
polytomous (PCM) items.
RMmartinLofresiduals().RMresidualPCA() for evaluating
patterns in the standardized residuals from the RM/PCM. Outputs either a
table with eigenvalues and explained variance or a figure with
standardized loadings on the first residual contrast and item
locations.RMpcaCutoff() to determine a
simulation-based critical value for the largest eigenvalue.RMbootRestscore() for use with
large sample sizes. See https://pgmj.github.io/rasch_itemfit/ for more
details.RMscoreSE() that produces a
transformation table (or figure) from ordinal sum scores to WLE
(Weighted Likelihood Estimation) interval scores.RMlocdepQ3cutoff() to improve speed.RMtargeting() for Wright map style
plots.mice.
RMinfitcutoff_mi() uses the
mids object containing multiple imputated datasets (output
by mice::mice()) to run simulations on each datasets and
combines the results. Splits iterations across imputations (e.g. 250
total / 5 imputations = 50 each).RMiteminfit_mi() calculates and pools
conditional infit from the imputated datasets and optionally uses the
RMinfitcutoff_mi() output for cutoff values.RMinfitcutoffPlot()RMpartgamLD() and
RMpgLDcutoff() for evaluating local
dependency of item pairs in both directions.
RMpgLDplot(), similar to
RMpgDIFplot()RMpartgamDIF() and
RMpgDIFcutoff() for evaluating DIF of
categorical external variables.
RMpgDIFplot(),
similar to RMinfitcutoffPlot()RMinfitcutoffPlot() to
illustrate distribution of simulated conditional item infit MSQ values
together with the observed value.RMinfitcutoff() gains
cutoff_method and hdci_width
parameters: By default (cutoff_method = "hdci",
hdci_width = 0.999), per-item cutoff intervals are now
computed using the Highest Density Interval via
ggdist::hdci() (99.9% HDCI). Set
cutoff_method = "quantile" to restore the previous
behaviour (2.5th/97.5th percentiles). The ggdist package is
only required when cutoff_method = "hdci" (added to
Suggests). The returned list now also includes
cutoff_method and hdci_width fields.
RMiteminfit() caption updated: When
cutoff is the return value of RMinfitcutoff(),
the kable caption now states the cutoff method, e.g.
"Cutoff values based on 250 simulation iterations (99.9% HDCI)."
or
"Cutoff values based on 250 simulation iterations (2.5th/97.5th percentile).".
RMiteminfit() gains optional
cutoff parameter: Accepts the return value of
RMinfitcutoff() (or its $item_cutoffs
data.frame directly). When provided, per-item cutoff boundaries
(Infit_low, Infit_high) and a logical
Flagged column are added to both "dataframe"
and "kable" output. The kable caption includes the number
of simulation iterations when available.
New RMinfitcutoff():
Simulation-based (parametric bootstrap) cutoff determination for
[RMiteminfit()]. Supports both dichotomous and polytomous data. Optional
parallel processing via mirai (falls back to sequential if
not installed). Returns per-item 2.5th and 97.5th percentiles of
simulated infit and outfit MSQ distributions
($item_cutoffs), together with the full iteration-level
results ($results). Requires the iarm package
(Suggests).
New RMiteminfit(): Computes
conditional infit MSQ statistics for each item via
iarm::out_infit(), enriched with item locations relative to
the sample mean person location. Supports both dichotomous (Rasch model
via eRm::RM()) and polytomous (Partial Credit Model via
eRm::PCM()) data. Requires the iarm package
(Suggests). Output options: "kable" (default, plain-text
knitr::kable()) or "dataframe". Optional
sort = "infit" sorts by infit MSQ descending. Only complete
cases are used for conditional fit calculation.
New RMitemrestscore(): Computes
observed and model-expected item-restscore correlations via
iarm::item_restscore(), enriched with absolute differences
between observed and expected values, item average locations, and item
locations relative to the sample mean person location. Supports both
dichotomous (Rasch model via eRm::RM()) and polytomous
(Partial Credit Model via eRm::PCM()) data. Requires the
iarm package (Suggests). Output options:
"kable" (default, plain-text knitr::kable())
or "dataframe". Optional sort = "diff" sorts
by absolute difference descending.
RMlocdepQ3(): cutoff is
now optional (default NULL). When omitted, the raw Q3
residual correlation matrix is returned without any dynamic cut-off
applied. When provided, the dynamic cut-off (mean Q3 + cutoff) is shown
in the kable caption as before. Supersedes the requirement to always
supply a cutoff value (PRs #2 and #3).RMlocdepQ3cutoff():
Simulation-based (parametric bootstrap) cutoff determination for
RMlocdepQ3(). Supports both dichotomous and polytomous
data. Optional parallel processing via mirai (falls back to
sequential if not installed). The $suggested_cutoff is the
99th percentile of the simulated Q3 max–mean distribution.R/utils-simulation.R: sim_poly_item(),
sim_partial_score(), and
extract_item_thresholds().eRm,
psychotools (>= 0.7-3), parallel, and
utils moved/added to Imports. mirai added to
Suggests.RMlocdepQ3() for Yen’s Q3 residual correlation
analysis of local dependence.