The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
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[@]dogado.de.
Ninth review round: one finding.
print() distinguishes the three saved-fit dependence
schemas by their df field: current fits label the statistic
t; 1.11.4 transitional fits (z name,
df present, t-based p) print as t; older fits
(z, no df, normal-reference p) KEEP the
z label – relabelling them t misrepresented
how their p-values were computed (a legacy z = 3.17 with normal p = .002
is not the same claim as t = 3.17 with p = .016 at five clusters). The
regression test now reconstructs both legacy schemas faithfully.Eighth review round: label and migration polish.
print() reads the dependence statistic from either the
current t column or the pre-1.11.5 z column,
so fits saved before the rename print completely; the printed label and
the rank-deficiency note both say t, matching the t(G - 1)
reference. No duplicate z alias column is added: the
package has never had a released version with the old name, the rename
is documented here, and old saved fits are read transparently.Seventh review round: three completions of round-six fixes, one label.
margin= gets the same explicit-ordering rule as
response=: an ORDERED factor (smallest to largest margin)
or a numeric magnitude; plain factors AND character columns are refused,
since alphabetical order could silently reverse which margin counts as
the big win.second_dim$items, and
a vector-valued rho.t, matching its t(G - 1) reference (at infinite df it is
the familiar z). The reviewer’s independent 400-run null simulation of
the cluster-t correction found 5.25% rejection at nominal 5%.Sixth review round: four findings, all verified and closed.
as.numeric(factor) returns level codes, so a factor score
of “1.9” slipped past as the integer 3 and was then truncated.
Non-numeric and non-finite scores now also error at every entry point
instead of silently becoming missing.btl() requires an ORDERED response factor: a
plain factor’s alphabetical level order silently defined – and could
reverse – the response scale (worse < same < better read as better
< same < worse). Integer scores 0..m remain the alternative.simulate_rasch() validates the second-dimension
specification: rho outside [-1, 1] and unknown item
names/indices are errors (rho = 1.2 used to produce an all-missing
second dimension that looked like a successful simulation), and the
item-set resolver now range-checks every nominated item list
centrally.Fifth review round: seven findings, all verified and closed.
pcml(),
pcml_pc(), and rasch_mfrm() truncated 1.9 to 1
silently, and graded btl() rounded it; only
rasch() rejected. One shared guard serves all entry
points.item_moments() is overflow-stable (log-sum-exp): a
31-category item, or wide categories with a large discrimination,
overflowed the uncentred exponent and turned every
person_wle() location NA.btl_efrm() rejects a judge assigned to more than one
panel (a panel is a judge attribute; the judge bootstrap would otherwise
silently reclassify rows).simulate_rasch()’s secondary trait keeps the requested
mean and sd (combining two mean-mu components had shifted the mean by
the factor rho + sqrt(1 - rho^2)) and is returned in the truth
metadata.Edge cases from the fourth review round, verified and closed:
as.integer(0.5) is a zero binomial size – every reference
draw degenerated to 0). The per-replicate leading strengths are exposed
as $reference$draws.btl_efrm(se_method = "judge_bootstrap") refuses a panel
with a single judge (resampling one judge returns the same data every
time, so its SEs would be a spurious zero) and notes panels with fewer
than five judges as rough.btl() notes when there are no more judge clusters than
parameters: the clustered covariance is then rank-deficient by
construction and no scalar (CR1) correction repairs it – the SEs likely
understate.The follow-up review’s residual findings, all verified and closed:
btl_efrm(se_method = "judge_bootstrap"): judges
resampled with replacement within panels and the whole pipeline
refitted, so the errors carry within-judge dependence as well as
stage-one uncertainty – closing the documented gap in the parametric
bootstrap. On model-true data it agrees with the parametric bootstrap;
estimates are unchanged by construction.Statistical validity, from a second external review. Every finding was re-derived or reproduced by simulation before fixing; the fixes are verified by new calibration tests (test-statistical-validity.R).
pcml()
recentres thresholds so the mean item location is zero, but the
covariance stayed under the sum-of-thresholds constraint – identical
only when every item has the same maximum score. With mixed
1/2/3-threshold items, per-item empSD/SE ran 0.90-1.21 by item type; the
linear transform (I - 1a') cov (I - a1') restores
0.96-1.09. Affects threshold and item SEs, separation, and equating
weights on mixed designs.disc[(R-E) + mu3/(2V)] – the
discrimination cancels; a stray disc factor in the
correction biased WLEs by up to 0.26 logits at disc = 0.5 (exact at disc
= 1, so ordinary analyses were unaffected; the vector-disc EFRM path was
already correct).adjust_N proportional-scaling semantics are now documented
explicitly.[(I - 1u') Sigma (I - u1')]_ii with Sigma the sum of the
two calibrations’ location covariances (a bank contributes diag(se^2)).
Null calibration: 4.6% rejection at nominal 5%, t-SD 0.97.btl_dif() now tests at the judge level: residuals
aggregate to one weighted mean per judge (per opponent band) and enter a
split-plot ANOVA with the judge as the error unit. The comparison-level
ANOVA pseudo-replicated – 6 of 10 null datasets with judge heterogeneity
and arbitrary groups falsely flagged uniform DIF; the judge-level design
flags 0 of 10 while still detecting a planted 1-logit effect. Band
breaks moved to count-weighted quantiles, making aggregated and expanded
data exactly equivalent. Power now scales with judges per group – the
honest unit.rasch()
and btl() (it was only visible in print);
btl()’s convergence flag is scale-free (gradient per
comparison).sim_replicate() recommended where exact calibration
matters; the BTL pair chi-squares are marked descriptive under judge
clustering; the next-pair priority is documented as a ranking heuristic;
the BTL dimensionality reference’s no-refit design is stated.Input honesty, from an external code review (five findings, all confirmed and fixed):
id, factors, or
items column names in rasch() are now errors
naming the missing columns; they were silently ignored (one misspelled
factor silently dropped ALL factors), producing valid-looking analyses
of the wrong data. Numeric item indices still work.as.integer() used to truncate them silently, altering
response data. Integer-valued doubles (“2.0”) still pass.paste() used to coerce NA
to the literal string “NA”, silently pooling unrelated rows under a
phantom level.equate_tests() excludes common items whose location or
SE is unavailable (e.g. weakly determined items with honest NA SEs) from
the precision-weighted shift and drift tests, notes them, and keeps
their rows with NA test columns – one such item used to turn every
statistic NA. plot_equate() handles the excluded rows.report_html() escapes all data-derived text (title,
notes, item and facet names) – crafted column names could inject markup
into reports; table cells were already escaped.compare_fits() gains cl_aic and
cl_bic (Varin & Vidoni 2005; Gao & Song 2010):
-2 cl penalised by the effective parameter count
tr(H^-1 J) from the Godambe matrices – the same quantity
whose eigenvalues calibrate lr_test() – which absorbs the
pairwise over-counting a nominal AIC/BIC would ignore (empirically
3.5-5x the nominal count). Verified by plant-and-detect: the criteria
select RSM on rating-structured data, PCM under varying threshold
spreads, and a planted BTL position effect – and reject the richer model
when the effect is absent. n for CL-BIC counts independent
units: persons contributing an informative pair, or judges
(count-weighted comparisons when unclustered). MFRM/EFRM fits report NA
with the reason noted.compare_fits() now accepts btl fits
(all-BTL comparisons: free vs principal-component thresholds,
with/without a position effect or within-judge dependence), reporting
judges/objects/comparisons and OSI. btl() fits carry their
composite-likelihood ingredients in $cl; anchored
pcml() and pcml_pc() now return their Godambe
matrices. The app’s Compare page shows the criteria and accepts
paired-comparison fits.pcml(), pcml_pc(), and everything built on
them now stop with an error naming the disconnected blocks. Anchors
rescue a block (disjoint-form equating): with an anchored item in every
block the fit proceeds; with any block unanchored it stops and names
it.thr$weak), their SEs and the item-location SE
reported as NA, and a note names the item, the category, and its count,
pointing to pc_components or category collapsing. Estimates
are still returned; categories with zero responses are rescored away as
before.inst/casestudies/party_blocs_crisis.R
applies btl_efrm() to the Tuebingen 2009 party-preference
data (via psychotools), with ideological blocs as object
sets and economic-crisis concern as judge panels. Running the model
against real data surfaced three defects, all fixed below.btl().?btl_efrm.btl_efrm() estimates object locations when the unit of the
scale differs across judge-panel by object-set frames – the package’s
extension of Humphry’s persons-by-items EFRM to the Bradley-Terry-Luce
family. Panel units (phi, a panel’s discriminating power) are identified
conditionally wherever two panels judge a common set; set units and
origins (alpha, kappa) are identified from cross-set comparisons, which
are themselves conditional outcomes – so, unlike the persons-by-items
case, the linking makes no distributional assumption about the objects.
Everything is estimated by the staged conditional estimator: the
within-frame calibrations are invariant to the linking data (the
frame-of-reference property), a deliberate trade of efficiency for
invariance. The cross-frame discrimination convention (cross-set
contests judged at exactly phi) is stated plainly in the documentation
as an assumption, with the per-frame fit residuals as its check.btl_efrm() defaults to a parametric
bootstrap of the whole two-stage pipeline: simulation showed the fast
conditional errors cover at a third of nominal on chain-linked designs
(they omit the stage-one uncertainty that flows into the linking), while
the bootstrap restores 12/12 coverage and nominal false-flag rates at
both small and large designs. The conditional errors remain available as
se_method = "conditional" for quick inspection, labelled as
understating. plot_btl_units() draws the unit caterpillar;
simulate_btl_efrm() generates frame-structured data with
planted units for the plant-to-detect loop.Three further paired-comparison analogues of the Rasch tool set, and CRAN housekeeping.
btl(anchors = c(Object = value, ...)) holds the named
objects at fixed locations and estimates the rest on that scale (no
sum-zero constraint; anchored objects report se 0) – the equating
workflow’s second half, mirroring rasch(anchors=). An
anchored object at a response boundary is an error rather than a silent
removal.btl(position = TRUE)
estimates the pure positional (first/left-presented) advantage of the
Davidson & Beaver
btl_equate() compares two
paired-comparison calibrations (or a calibration against a bank) through
their common objects – precision-weighted origin shift, per-object drift
t-tests with multiplicity adjustment, equated locations – with
plot_btl_equate(); the standards-maintenance workflow of
comparative judgement across panels or years.btl_information()
(per-comparison Fisher information and per-object design information,
with the naive 1/sqrt(information) SE beside the judge-clustered
sandwich), plot_btl_targeting(), and
btl_next_pairs() – the greedy most-informative-next-pair
step of adaptive comparative judgement (Pollitt 2012), with the Bramley
(2015) reliability-inflation caution documented.skip_on_cran() (they run locally and on CI), and
cran-comments.md drafted from a full --as-cran
check (about 3 minutes; slowest example 1.4s).btl(count=)
inflated every sandwich standard error by about the square root of the
count (the meat weighted aggregated rows twice; point estimates were
always correct). Count- weighted fits now reproduce the expanded-data
standard errors exactly; OSI and all z/p values follow. Additionally
from that round: btl_equate()’s shift standard error now
uses the stored covariance of each calibration (it treated the
common-object differences as independent, overstating the SE
several-fold; 95 per cent coverage verified) and documents the
majority-drift limitation of single-shift equating;
btl_next_pairs() ranks by the exact one-step reduction in
total location variance (a Sherman-Morrison update on the fit’s
covariance), verified to beat low-priority pairs empirically; and
btl_information()’s se_naive is documented
honestly as a single-parameter lower bound rather than an independence
benchmark.A statistical audit of the new simulation and paired-comparison independence code (23 findings across two adversarial rounds, all fixed), plus a vignette and a logo.
Misfit layers now compose correctly in
simulate_rasch(): the response-dependence and
response-style regeneration steps previously rebuilt their target items
from the base structure, silently erasing any DIF or second-dimension
loading planted on those items (and leaking a DIF-like signal from a
DIF-carrying source item into its dependent partner). Every regeneration
now honours the item’s own generating structure – trait, group-shifted
thresholds and slope, guessing.
btl_dimensionality() now simulates its noise
reference sequentially WITH the fitted within-judge dependence effects
when the fit carries them: real order effects previously inflated the
false-positive rate to ~36 per cent on one-dimensional data (now ~0-5
per cent). The documented price is conservatism, since carry-over and a
judge-camp second attribute are partially confounded.
Doc examples pass id = "id" so they no longer emit
spurious dropped-column notes.
simulate_rasch(): model = "PCM" now
draws each item’s threshold spacings and span afresh, as the partial
credit model allows (previously PCM and RSM generated identical
rating-scale-structured data); dif without
n_groups >= 2 is an error instead of a silent no-op;
polytomous guessing warns and is ignored rather than
falsely recorded as planted; the response-dependence term now carries
the guessing asymptote of the pair’s first item (no more spurious
easiness on the dependent item); disordered thresholds work with 3
categories and no longer shift the item’s location; careless responders
are no longer double-counted as response-style persons in the recorded
truth.
simulate_mfrm(): halo raters are capped at the
eligible pool (no NA raters when erratic raters shrink it); the example
runs.
sim_recovery(): person abilities are mean-centred as
documented (an asymmetric difficulty range no longer masquerades as
person bias); the many-facet branch reads the item margins
(item_effects), restoring the documented item-difficulty
recovery for MFRM fits.
btl_dimensionality(): null calibration verified for
graded fits (mildly conservative, never anticonservative) and
documented; docs also clarify the leading-bimension reference columns
and the no-ties precondition of Kendall’s zeta.
Shiny app (Simulate page): the parameter-recovery card only renders when the current fit was estimated on the currently loaded simulation (a stale fit can no longer be compared against new truth); the reproducible call now carries every argument the generator received (MFRM person/item SDs, EFRM person SD, graded categories); non-integer seeds are rounded safely.
New vignette: “Planting misfit and watching the diagnostics fire”
— the plant-to-detect loop end to end, closing with a small Monte Carlo
power estimate via sim_replicate().
A hex logo (an item characteristic curve at its location),
reproducible from tools/logo.R.
judge_surprise() and plot_btl_judge_map():
the paired-comparison counterpart of the kidmap. A judge has no ability
to condition on, so the reference is the consensus object scale; each
object a judge met gets a standardised residual saying how much more or
less that judge favoured it than its location predicts. A strong object
the judge under-rated, or a weak object over-rated, is an unexpected
judgement. It catches systematic bias – a distinct failure mode from the
noise that judge fit and judge consistency flag. In the Shiny app the
Persons > Judge fit panel is now a master-detail: the judges table
drives the selected judge’s map, mirroring person -> kidmap.btl_transitivity() counts circular triads (preference
loops: A beats B, B beats C, C beats A) against the chance rate, reports
Kendall’s coefficient of consistency for complete designs, and gives
each judge’s own consistency (Kendall & Babington Smith 1940) – the
single-dimension check, and a judge-fit analogue.btl_dimensionality() decomposes the skew-symmetric
object-by-object residual preference matrix into Gower (1977) bimensions
– the paired-comparison counterpart of residual PCA – and judges the
leading bimension against a model-simulated noise reference, so a
coherent residual “swirl” (a second attribute steering some contests) is
distinguished from noise.plot_btl_scree(), plot_btl_dim_map(), and
plot_btl_transitivity() display them; the Shiny app’s
Independence > Trait tab now carries these for a BTL fit (it
previously hid for paired comparisons).rmt). The name rmt
belongs to an unrelated package on CRAN, and rasch says
plainly what this is – and mirrors mirt::mirt() with
rasch::rasch(). No functions, arguments, or results change;
only the package and library name. The auxiliary result classes were
unified under the rasch_ prefix (rasch_btl,
rasch_dif, …) to match the fit classes.A full statistical audit of the independence, invariance, and paired- comparison procedures, with fixes throughout.
btl() now interrogates within-judge
dependence – dependence_data holds every comparison’s
exposure and carry-over covariates (count-weighted),
plot_btl_dependence() displays an effect as a
partial-residual curve, and a separated effect (one-sided informative
comparisons) is set aside with a note instead of reported as a runaway
estimate. The graded engine’s threshold-by-dependence Hessian block is
corrected (free-threshold fits with five or more categories and an order
column now converge), rows with a missing judge are dropped with a note,
category checks re-run after boundary objects are removed, and the
dichotomous path now routes through the one (vectorised) estimator.btl_dif() holds fitted dependence effects fixed in its
residual moments and resolution refits (dependence is no longer absorbed
as spurious judge-group DIF), weights count-aggregated comparisons
exactly as expanded rows, restricts supersession to group terms, and
notes every significant term it does not resolve.dif_anova() keeps each ANOVA term in its own error
stratum, so a mixed (within-subject) design with missing responses no
longer un-flags real DIF; factors named like internals (ci,
f1) are safe; a term’s own class-interval crossing no
longer supersedes it (so resolve_dif() again splits items
with both uniform and non-uniform DIF); mixed designs say plainly that
Tukey comparisons are unavailable; and dif_size() notes
when a within-person factor makes its standard errors conservative.plot_scree()’s parallel-analysis reference is now
model-simulated (responses drawn from the calibrated model, persons
re-estimated), so model-true data sits at the reference instead of
always “showing structure” (Raiche 2005; Chou & Wang 2010).plot_pca_biplot() draws the item loadings on the
first two residual principal components – the pair that usually carries
any interpretable contrast – on equal axes, coloured by the sign of the
PC1 loading.
residual_correlations() now also returns the
adjusted-Q3 star_matrix (each Q3 less the average
off-diagonal), and plot_resid_cor() gains a
stat argument to colour either the raw Q3 or the adjusted
Q3*, drawing the lower triangle only.
Shiny app: the trait- and local-dependence pages pair each table with its plot (loadings with a PC1-PC2 biplot; Q3 and Q3* matrices with heatmaps), the raw and adjusted correlations are each flagged by their own rule (|Q3| and Q3*), and every data-restructuring action (subtest, item split, automatic DIF resolution) offers an in-place reset to the original data.
dif_anova() is now the single DIF
analysis-of-variance function. One factor is analysed one-way; several
factors are modelled jointly – the statistically correct treatment –
with main effects by default and factor-by-factor interactions optional
(effects = "factorial"). It handles within-subject factors
(repeated-measures / mixed ANOVA) and returns a classed object with a
summary, the full terms table, and Tukey
comparisons. The separate dif_anova_factorial() is
removed.
resolve_dif() resolves DIF iteratively by item
splitting, largest effect first, to clear artificial DIF.
First stable release. The package delivers a complete Rasch Measurement Theory workflow built entirely from published measurement theory, with a pairwise conditional estimation core and a Shiny interface that exposes every analysis with reproducing R code attached to every output.
rasch(): dichotomous and polytomous (partial credit and
rating scale) Rasch models by pairwise conditional maximum likelihood
(Andrich & Luo 2003; Zwinderman 1995), with Godambe sandwich
standard errors, sum-zero identification, Warm (1989) weighted
likelihood person estimation, and the principal-component threshold
parameterisation as an estimation option.rasch_mfrm(): many-facet models with additive facet
severities or item-by-facet interactions, accepting wide (one column per
item) or long data.rasch_efrm(): the extended frame-of-reference model
(Humphry) with frame units estimated by within-frame pairwise
conditional likelihood.btl(): paired comparisons as the conditional form of
the dichotomous Rasch model (Bradley & Terry 1952; Andrich 1978),
including the adjacent-categories graded extension (Tutz 1986; Agresti
1992) with symmetric thresholds – the Davidson (1970) ties model is its
three-category case – winner-plus-margin data entry, judge-clustered
errors, and within-judge exposure and carry-over effects estimated
jointly with the locations.btl_dif() tests object-by-judge-group
interaction by the same two routes.fit_summary_table() and targeting_table()
return the headline statistics as tidy tables;
save_outputs() writes every table and plot to disk;
report_html() produces a single-file HTML report.run_app() launches the Shiny interface: model-adaptive
navigation, reproducing R code beneath every output, and one-click
export.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.
Health stats visible at Monitor.