| Title: | Item Response Theory for Large Sparse Data |
|---|---|
| Description: | Fits binary item response theory (IRT) models for large and sparse data in long format, by marginal maximum likelihood with a Laplace approximation to the integral over person abilities, or by the joint posterior mode over items and persons. Supports 1PL to 4PL models, multidimensional and confirmatory loading structures with an estimated latent correlation, covariate effects on ability and on each item parameter, empirical-Bayes prior adaptation, and post-estimation tools for information, reliability, item fit, held-out prediction and simulation. |
| Authors: | Charles Driver [aut, cre] (ORCID: <https://orcid.org/0000-0002-4174-2970>) |
| Maintainer: | Charles Driver <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-10-21 12:31:27 UTC |
| Source: | https://github.com/cdriveraus/bigIRT |
Opens mirt's diagnostic suite – itemfit(), personfit(), M2(),
residuals(type = "Q3"), itemplot(), DIF() – none of which is worth
reimplementing, because all of them need the wide person-by-item matrix and
that, not the arithmetic, is the binding constraint. Data too large to hold
as one cannot cross, and is refused rather than attempted.
as.mirt(fit, max_cells = 5e+07, verbose = FALSE)as.mirt(fit, max_cells = 5e+07, verbose = FALSE)
fit |
A fitted object from |
max_cells |
Numeric. Refuse a wide matrix larger than this. |
verbose |
Logical. Passed to |
A SingleGroupClass object with every parameter fixed at this
fit's values.
checkMirtBridge(), which verifies the translation.
Returned in the order the data were supplied, so the result can be bound
back onto the caller's own data frame. Registered against broom::augment()
when broom is installed.
augmentIRT(x, ...)augmentIRT(x, ...)
x |
A fitted object from |
... |
Unused. |
A data frame of row index, observed response, fitted probability, training flag, residual and standardised residual.
A single scaled gradient norm cannot say which block failed to settle, it hides one stuck parameter among thousands, and a small block whose gradient aggregates over many units can dominate it. This reports per-block norms and shares, the worst parameter measured in its own standard errors, and the Newton decrement, which estimates how much objective is still available.
checkConvergence(fit, cores = 1L, se = TRUE)checkConvergence(fit, cores = 1L, se = TRUE)
fit |
A fitted object from |
cores |
Integer. Cores for the information calculation. |
se |
Logical. Compute the item information needed for the Newton decrement and the worst-parameter measure. |
An object of class bigIRT_convergence, carrying blocks,
newton_decrement, objective_remaining, worst_parameter_se_units and
the fit's certificate.
The decrement uses the block-diagonal item curvature, the same model the
Newton polish steps in, so it is self-certifying. Compare decrements within
one algorithm, and compare algorithms by the objective. The certificate a
Laplace fit carries (fitIRT(laplaceCertify = )) is computed on the exact
Hessian of the fitted objective instead; it is returned as certificate,
and it is the verdict converged follows.
Compares mirt's own trace lines against bigIRT's response function on a grid of abilities. This tests the parameter translation directly, without marginalisation, so a coercion error is separated from the difference between Laplace and quadrature. A coercion that is quietly wrong produces diagnostics that look entirely reasonable, which is why this exists.
checkMirtBridge( fit, mirt_fit = NULL, theta = seq(-3, 3, 0.5), tolerance = 1e-06, max_items = 25L )checkMirtBridge( fit, mirt_fit = NULL, theta = seq(-3, 3, 0.5), tolerance = 1e-06, max_items = 25L )
fit |
A fitted object from |
mirt_fit |
Optional object from |
theta |
Numeric vector of ability points. |
tolerance |
Numeric. Largest acceptable probability difference. |
max_items |
Integer. Items to check. |
An object of class bigIRT_mirtcheck.
Coerces simulated truth, bigIRT fits, and mirt fits onto a common raw
and normalized parameter representation for direct comparison.
compareIRTmodels( models, score_method = "EAP", normaliseScale = 1, normaliseMean = 0, curveSampleN = 50L )compareIRTmodels( models, score_method = "EAP", normaliseScale = 1, normaliseMean = 0, curveSampleN = 50L )
models |
A named or unnamed list containing up to one |
score_method |
Character string passed to |
normaliseScale |
Numeric scalar passed to |
normaliseMean |
Numeric scalar or vector passed to |
curveSampleN |
Integer. Number of multivariate-normal theta draws used to compute item-response-curve RMSE against the reference model for each item and form. Default is 50. |
Which form to read: when every model identifies its metric the way the
reference does – the same fixed latent distribution, a confirmatory
loading pattern – the "raw" form is already on the reference's metric and
is the one to compare. The "normalized" form standardises each model by
the spread of its own ability estimates, which for a fitted model are point
estimates shrunk toward the prior mean: it flattens the fitted loadings by
roughly the square root of the reliability (about a fifth at ten responses
per person) while the reference, standardised by its true abilities, is
left alone, and so favours models with steeper loadings. Use it only when
the metrics genuinely differ, and treat its curve RMSE accordingly.
A list with elements itempars, personpars, loading_matrix,
ability_corr_matrix, raw, normalized, and reference_model.
Each table is in long format with a source column, a source-specific
value column, and a referenceVal column holding the aligned value from
the reference model.
This function drops variables/items and subjects that have all perfect scores (either all 0's or all 1's) in a data table.
dropPerfectScores( dat, scoreref. = "score", itemref. = "Item", idref. = "id", tol. = 0.001, trainref. = NULL )dropPerfectScores( dat, scoreref. = "score", itemref. = "Item", idref. = "id", tol. = 0.001, trainref. = NULL )
dat |
The input data table |
scoreref. |
The column name of the score variable in |
itemref. |
The column name of the item variable in |
idref. |
The column name of the id variable in |
tol. |
Tolerance level for checking perfect scores – .01 would drop subjects with less than 1% correct or incorrect |
trainref. |
Optional name of a 0/1 column marking training rows. When
given, whether a person or item is perfect is decided from its training
rows only, and all its rows (held-out ones too) are dropped; a person or
item with no training rows is kept. |
The input data table (dat) without variables/items and subjects with all perfect scores.
dat <- data.table(id=c(1,1,1,2,2,2,3,3,3), Item=c('I1','I2','I3','I1','I2','I3','I1','I2','I3'), score=c(1,0,1,0,0,0,0,1,1)) print(dropPerfectScores(dat))dat <- data.table(id=c(1,1,1,2,2,2,3,3,3), Item=c('I1','I2','I3','I1','I2','I3','I1','I2','I3'), score=c(1,0,1,0,0,0,0,1,1)) print(dropPerfectScores(dat))
People are binned by fitted ability and the observed proportion correct in each bin is compared with the model's prediction, which says how an item misfits rather than only that it does.
empiricalICC( fit, items = NULL, bins = 10L, scale_index = 1L, training_only = TRUE )empiricalICC( fit, items = NULL, bins = 10L, scale_index = 1L, training_only = TRUE )
fit |
A fitted object from |
items |
Optional item index to restrict to. |
bins |
Integer. Number of ability bins. |
scale_index |
Integer. Latent dimension to bin on. |
training_only |
Logical. Use training rows only. |
A data frame of item, bin, count, mean ability, observed and expected proportion, and a Wilson interval.
Bins are formed on estimated ability, which is shrunk and measured with error, so people sort partly by noise and the observed curve flattens against the model. On correctly specified data the model falls inside the nominal 95 per cent interval for about 80 per cent of bins. Read a mild symmetric shortfall as that artefact, and a one-sided or localised departure as misfit.
Arranges the score contributions of scoreContributions() as the matrix
sandwich::estfun() returns: one row per person (the person's marginal
score, summed over their responses) or per response, one column per free
item parameter. Tools built on estfun, such as the generalised
fluctuation tests of strucchange::gefp() and strucchange::sctest(),
then run on a bigIRT fit as they do on mirt fits.
estfun.bigIRT_scores( x, items = NULL, parameters = c("B", "A", "C", "D"), level = c("person", "row"), ... )estfun.bigIRT_scores( x, items = NULL, parameters = c("B", "A", "C", "D"), level = c("person", "row"), ... )
x |
A |
items |
Items to include (default all). Each free parameter is a column, so for large banks choose items. |
parameters |
Parameter types to include: any of |
level |
|
... |
Unused. |
Persons are independent and are the units such tools assume; responses
within a person are not, so level = "row" is for bookkeeping (a
covariate given per response), not for tests that treat rows as
independent – scoreTest() handles those. Those tools decorrelate with
the outer product of these scores; scoreTest() uses each response's
expected information instead, which on thin items is better calibrated.
A matrix with rows in the order of x$persons (or x$rows) and
columns named item:parameter.
## Not run: sc <- scoreContributions(fit) z <- covariate_per_person[as.integer(sc$person_labels)] gp <- strucchange::gefp(sc, fit = NULL, order.by = z, scores = function(x) sandwich::estfun(x, items = "item7")) strucchange::sctest(gp, functional = "DM") ## End(Not run)## Not run: sc <- scoreContributions(fit) z <- covariate_per_person[as.integer(sc$person_labels)] gp <- strucchange::gefp(sc, fit = NULL, order.by = z, scores = function(x) sandwich::estfun(x, items = "item7")) strucchange::sctest(gp, functional = "DM") ## End(Not run)
Extracts a common set of multidimensional IRT parameters from either a
bigIRT fit or a mirt fit.
extractMIRTpars(object, score_method = "EAP")extractMIRTpars(object, score_method = "EAP")
object |
A fitted |
score_method |
Character string passed to |
A list with components source, A, B, C, D, Ability,
corr, and latent_mean and latent_sd: the mean and standard
deviation of the latent variable on the solution's own metric, which is
what a normalisation should use. Ability holds point estimates, whose
spread understates the latent scale. For a bigIRT fit they come from the
posterior by the law of total variance (variance of the posterior modes
plus the mean posterior variance), for a mirt fit from its estimated
latent distribution; they are NULL for a simulation, whose Ability is
the latent variable itself, and for a fit that kept no posterior
precision.
Fits a 1PL to 4PL model to long-format binary response data, in one or
more dimensions, with optional covariates on ability and on every item
parameter. Two estimators are available through marginalApprox, and they
take the same arguments and return the same kind of object:
fitIRT( dat, score = "score", id = "id", item = "Item", scale = "Scale", pl = 1, marginalApprox = c("laplace", "map", "none", "laplace_fast", "laplace_direct"), personDat = NA, personPreds = character(), itemDat = NA, loadings = NA, loadingsFixed = NA, signedLoadings = NULL, AitemPreds = character(), BitemPreds = character(), CitemPreds = character(), DitemPreds = character(), itemSpecificBetas = FALSE, betaScale = 10, priors = TRUE, invspAMeandat = 0.542, invspASD = 1, BMeandat = 0, BSD = 2.5, logitCMeandat = 0, logitCSD = 1, logitDMeandat = 0, logitDSD = 1, AbilityMeandat = array(0, dim = c(length(unique(dat[[scale]])))), AbilitySD = array(1, dim = c(length(unique(dat[[scale]])))), AbilityCorr = diag(1, c(length(unique(dat[[scale]])))), AMeanSD = 1, BMeanSD = BSD, logitCMeanSD = logitCSD, logitDMeanSD = logitDSD, AbilityMeanSD = array(1, dim = c(length(unique(dat[[scale]])))), estMeans = c("A", "B", "C", "D"), estimateAbilityCorr = "auto", laplaceCorrParam = c("stan_corsqrt", "normalized_chol"), ebayes = FALSE, ebayesMethod = c("laplace", "moment"), ebayesIter = 5L, ebayesCoarse = 1000, ebayesMinSD = 0.05, ebayesmultiplier = 2, laplaceRefine = c("auto", "agq", "laplace2", "none"), agqNodes = NULL, agqPoints = NULL, laplaceOptimizer = c("fisher", "mize"), laplaceOuterIter = 500, laplaceTol = 1e-04, laplaceGradTol = 1e-04, laplaceTolScale = c("relative", "per_obs"), laplacePolish = NA, laplacePersonTol = 1e-06, laplaceCertify = TRUE, laplaceJitter = 1e-06, laplaceKeepCovariance = FALSE, laplaceDiagnostics = FALSE, laplacePlot = FALSE, laplacePlotEvery = 1L, normalise = FALSE, normaliseScale = 1, normaliseMean = 0, dropPerfectScores = FALSE, trainingRows = 1:nrow(dat), cores = 6, verbose = 0L, keepInternals = FALSE, startFrom = NULL, abilityBetaMap = NULL, ... )fitIRT( dat, score = "score", id = "id", item = "Item", scale = "Scale", pl = 1, marginalApprox = c("laplace", "map", "none", "laplace_fast", "laplace_direct"), personDat = NA, personPreds = character(), itemDat = NA, loadings = NA, loadingsFixed = NA, signedLoadings = NULL, AitemPreds = character(), BitemPreds = character(), CitemPreds = character(), DitemPreds = character(), itemSpecificBetas = FALSE, betaScale = 10, priors = TRUE, invspAMeandat = 0.542, invspASD = 1, BMeandat = 0, BSD = 2.5, logitCMeandat = 0, logitCSD = 1, logitDMeandat = 0, logitDSD = 1, AbilityMeandat = array(0, dim = c(length(unique(dat[[scale]])))), AbilitySD = array(1, dim = c(length(unique(dat[[scale]])))), AbilityCorr = diag(1, c(length(unique(dat[[scale]])))), AMeanSD = 1, BMeanSD = BSD, logitCMeanSD = logitCSD, logitDMeanSD = logitDSD, AbilityMeanSD = array(1, dim = c(length(unique(dat[[scale]])))), estMeans = c("A", "B", "C", "D"), estimateAbilityCorr = "auto", laplaceCorrParam = c("stan_corsqrt", "normalized_chol"), ebayes = FALSE, ebayesMethod = c("laplace", "moment"), ebayesIter = 5L, ebayesCoarse = 1000, ebayesMinSD = 0.05, ebayesmultiplier = 2, laplaceRefine = c("auto", "agq", "laplace2", "none"), agqNodes = NULL, agqPoints = NULL, laplaceOptimizer = c("fisher", "mize"), laplaceOuterIter = 500, laplaceTol = 1e-04, laplaceGradTol = 1e-04, laplaceTolScale = c("relative", "per_obs"), laplacePolish = NA, laplacePersonTol = 1e-06, laplaceCertify = TRUE, laplaceJitter = 1e-06, laplaceKeepCovariance = FALSE, laplaceDiagnostics = FALSE, laplacePlot = FALSE, laplacePlotEvery = 1L, normalise = FALSE, normaliseScale = 1, normaliseMean = 0, dropPerfectScores = FALSE, trainingRows = 1:nrow(dat), cores = 6, verbose = 0L, keepInternals = FALSE, startFrom = NULL, abilityBetaMap = NULL, ... )
dat |
A data frame containing the data to be analyzed. |
score |
Character. The name of the column in |
id |
Character. The name of the column in |
item |
Character. The name of the column in |
scale |
Character. The name of the column in |
pl |
Integer. The number of parameters for the logistic model (1PL, 2PL, 3PL, or 4PL). Default is 1. |
marginalApprox |
Character. The estimator.
The Laplace curvature at the person mode is the observed Hessian, the actual second derivative of the log posterior. Fisher information was used until September 2026 and was selectable for a while after; it is neither now. Two reasons. Laplace approximates one integrand, so it needs that integrand's curvature rather than an average over responses the person did not give. And the mode adjoint applies the implicit function theorem, which needs the inverse of the actual Hessian: with Fisher in that role the item gradient missed the true total derivative by 1e-3 to 4e-2 for the 3PL and 4PL, at one, two and three dimensions. The 2PL is exact either way, because the logit link is canonical and the two curvatures are then the same number – which is why it went unnoticed for so long. Fisher information is still used for the Newton step, where its guaranteed positive definiteness is what makes the mode solve robust. Where the data's own contribution to the curvature is not positive semidefinite, it is clipped to the nearest matrix that is, rather than swapped for Fisher: swapping is discontinuous in the item parameters and a line search cannot cope with it. A consequence worth knowing is that the reported person posterior SD can never exceed the ability prior SD.
Predictor columns are response-row aligned and can vary within a person
or item, under either estimator; the likelihood retains their exact row
values while reported person and item summaries use within-entity
predictor means. |
personDat |
Data frame. Any fixed ability data for persons. Default is NA. |
personPreds |
Character vector. Names of predictors for person parameters found in data. Default is an empty character vector. |
itemDat |
Data frame. Any fixed item data. Default is NA. |
loadings |
Optional numeric matrix (
Row names are matched to item ids and column names are matched to scale ids when provided. |
loadingsFixed |
Optional logical matrix ( |
signedLoadings |
Which free loadings may take either sign. Every free
loading is otherwise the softplus
A signed loading's prior is normal with mean zero and SD Signs do not identify a rotation: with cross-loadings free in both
directions the dimensions can rotate into each other unless |
AitemPreds |
Character vector. Names of predictors for item discrimination parameters. Default is an empty character vector. |
BitemPreds |
Character vector. Names of predictors for item difficulty parameters. Default is an empty character vector. |
CitemPreds |
Character vector. Names of predictors for item guessing parameters. Default is an empty character vector. |
DitemPreds |
Character vector. Names of predictors for item upper asymptote (slipping) parameters. Default is an empty character vector. |
itemSpecificBetas |
Logical. Whether to allow item-specific betas for covariate effects, or simply estimate one effect per covariate. Default is FALSE. |
betaScale |
Numeric. Scale of the prior for beta parameters. Default is 10. |
priors |
Logical. Whether to use prior distributions. Default is TRUE. |
invspAMeandat |
Numeric. Mean for the prior distribution of the raw discrimination parameters, which subsequently have a 'softplus' log(1+exp(x)) applied. Default is 0.542, giving a mean for A pars of ~ 1. |
invspASD |
Numeric. Standard deviation for the prior distribution of the raw discrimination parameters. Default is 1. |
BMeandat |
Numeric. Mean for the prior distribution of the item difficulty parameters. Default is 0. |
BSD |
Numeric. Standard deviation for the prior distribution of the
item difficulty parameters. Default is 2.5, on the scale of
|
logitCMeandat |
Numeric. Mean for the prior distribution of the item guessing parameters (on logit scale). Default is 0. |
logitCSD |
Numeric. Standard deviation for the prior distribution of the item guessing parameters (on logit scale). Default is 1. The previous default of 5 carried a prior precision of 0.04, which is negligible against any data, so per-item guessing was effectively unconstrained; 1 gives precision comparable to what a handful of responses provide. Note that guessing is generally not recoverable per item at realistic test lengths – fitted values correlate with the truth at around .07 on 20 responses an item – so this prior mostly decides how firmly items pool towards a common asymptote. |
logitDMeandat |
Numeric. Mean for the prior distribution of the item upper asymptote parameters (on logit scale). Default is 0. |
logitDSD |
Numeric. Standard deviation for the prior distribution of
the item upper asymptote parameters (on logit scale). Default is 1, for
the reasons given under |
AbilityMeandat |
Numeric array. Mean for the prior distribution of the ability parameters. Default is 0 for each scale. |
AbilitySD |
Numeric array. Standard deviation for the prior distribution of the ability parameters. Default is 1 for each scale. |
AbilityCorr |
Matrix. Correlation matrix for the ability parameters. Default is an identity matrix. |
AMeanSD |
Numeric. Standard deviation for the prior distribution of the discrimination parameters. Default is 1. |
BMeanSD |
Numeric. Standard deviation for the prior distribution of the difficulty parameters. Default is |
logitCMeanSD |
Numeric. Standard deviation for the prior distribution of the guessing parameters (on logit scale). Default is |
logitDMeanSD |
Numeric. Standard deviation for the prior distribution of the upper asymptote parameters (on logit scale). Default is |
AbilityMeanSD |
Numeric array. Standard deviation for the prior distribution of the ability parameters. Default is 1 for each scale. |
estMeans |
Character vector. Which means to estimate, from 'ability',
'A', 'B', 'C', 'D'. Default is The ability mean and the difficulty mean cannot both be estimated. Adding a constant to every ability and the same constant to every difficulty leaves every response probability unchanged, so the location of the scale has to be pinned by one or the other. The default pins it through the ability prior; passing 'ability' here estimates the ability mean instead and requires dropping 'B'. This matters when whole persons are held out of |
estimateAbilityCorr |
|
laplaceCorrParam |
Character. Parameterisation used for the latent
correlation when |
ebayes |
Logical. Whether to use empirical Bayes estimation: the priors are adapted from a first-pass estimate. Default FALSE since 0.1.9 (TRUE before). On simulated 3PL and 4PL data, empirical-Bayes priors narrowed toward the first pass left item intervals covering .004 to .84 of the time against a nominal .95, where the fixed default priors were conservative. |
ebayesMethod |
Character. How prior
hyperparameters when |
ebayesIter |
Integer. Maximum empirical-Bayes rounds. Each round
refits, updates the prior hyperparameters from the fit by the EM M-step
for a normal-normal hierarchy, and stops early once every hyperparameter
moves by less than a thousandth. Ignored when |
ebayesCoarse |
Numeric. Tolerance multiplier for the intermediate
empirical-Bayes refits. Those rounds exist only to
produce estimates to update the hyperparameters from, so they are run at
|
ebayesMinSD |
Numeric. Floor on a prior SD estimated by
|
ebayesmultiplier |
Numeric. Multiplier on the prior SDs estimated by
|
laplaceRefine |
Character. Laplace estimator only (for
|
agqNodes |
Integer. Gauss-Hermite nodes per dimension for
|
agqPoints |
Integer. If given, beyond three dimensions the refinement
uses this many quasi-Monte Carlo points per person instead of the
pairwise expansion, in antithetic pairs, as importance sampling through
the Laplace Gaussian. Held fixed during the fit they can be exploited
unless there are many thousands. Default |
laplaceOptimizer |
Character. Optimiser, under either estimator.
|
laplaceOuterIter |
Integer. Maximum optimiser iterations, under either estimator. This is a fallback limit rather than the primary convergence criterion. Default is 500. |
laplaceTol |
Numeric. Optimiser tolerance, under either estimator.
Under |
laplaceGradTol |
Numeric. Tolerance for the item-block gradient,
measured relative to the objective rather than as a raw norm: the reported
norm is divided by the same denominator |
laplaceTolScale |
Character. What the scaled gradient norm compared
against |
laplacePolish |
Integer. Maximum block-Newton polish steps taken after
the quasi-Newton optimizer stops, on the final fit only. L-BFGS gives up
early on large problems: at eight million responses it reported no further
progress while a single Newton step still recovered 146 units of objective.
The curvature is the per-item information already used for standard errors,
so a step costs one closed-form assembly and a short backtracking search.
Applies to |
laplacePersonTol |
Numeric. Newton tolerance for person-mode updates in
|
laplaceCertify |
Logical, character or numeric. How to certify convergence on the Laplace path, on the curvature of the objective the fit ended on (Laplace, or the refined marginal). The optimiser's own stopping rule is a limited-memory estimate of the same quantity and cannot see a transform that has gone flat, where the gradient and the curvature vanish together (a correlation parked at 1.000 with a gradient of exactly zero); the certificate can. The fit is certified when the predicted gain
|
laplaceJitter |
Numeric. Small jitter added to stabilise the person precision factorisations. Default is 1e-6. |
laplaceKeepCovariance |
Logical. Whether to keep each person's
posterior covariance matrix ( |
laplaceDiagnostics |
Logical. Whether to store per-evaluation
optimiser diagnostics in |
laplacePlot |
Logical. Whether to draw the optimiser diagnostic plot during fitting. Default is FALSE. |
laplacePlotEvery |
Integer. Plot every N outer iterations when
|
normalise |
Logical. Whether to normalize the output estimates. Default is FALSE. |
normaliseScale |
Numeric. Scale for normalization. Default is 1. |
normaliseMean |
Numeric. Mean for normalization. Default is 0. |
dropPerfectScores |
Logical. Whether to drop subjects and items whose
training responses are all correct or all wrong before estimation.
Default is FALSE (TRUE until October 2026). Neither estimator needs it:
the ability prior keeps such a person's ability finite, and the item
priors keep such an item's parameters finite. Dropping them is not
harmless. All-correct and all-wrong students are exactly the responses
that speak against a free asymptote, and with them dropped the score test
of an upper asymptote rejected 15 per cent of true nulls on a simulated
adaptive bank (5 with them kept). With |
trainingRows |
Integer vector. Rows of data to use for estimation of
parameters. Default is all rows in |
cores |
Integer. Threads for the person-level kernels. Default is 6. |
verbose |
Integer. 0 is silent; 1 reports the start and end of the fit and each empirical-Bayes round; 2 adds a line per objective evaluation and the optimiser's timing summary. Default is 0. |
keepInternals |
Logical. Attach the prepared data ( |
startFrom |
Optional: a previous fit from |
abilityBetaMap |
Optional: which person-predictor coefficients are
estimated, as a matrix with the scales as row names and the person
predictors as column names. 0 holds an entry at zero, and entries with
the same positive number share one coefficient; entries the matrix does
not name are each free, as they are without a map. With several
dimensions this makes a covariate's effect common to them (one number
across a column) or absent from one (0), as when a dimension is to be
judged on the dependence it explains rather than on a group difference
it could absorb ( |
... |
Accepted only for arguments of earlier versions, so that old
code keeps running. |
"laplace" (default)Marginal maximum likelihood (or posterior
mode, with priors): the abilities are integrated out by a Laplace
approximation at each person's mode, refined by adaptive quadrature where
Laplace is biased (laplaceRefine).
"map"The joint posterior mode over item parameters and
abilities together. Each evaluation solves every person's mode and
differentiates the joint posterior at it, so it is cheaper per evaluation
than Laplace, and much cheaper than Laplace refined by quadrature. Its
latent scale is set by the priors rather than the data (see
marginalApprox).
Both run the same optimiser over the item-side parameters with every person
mode solved inside each evaluation, so the optimiser controls
(laplaceOptimizer, laplaceTol, laplaceOuterIter, laplacePersonTol,
laplaceCertify, ...) apply to either; the laplace prefix is historical.
An object of class bigIRT_fit, the same under either
estimator. Its main parts:
itemPars, personPars
Item parameters (one row per
item, with a column per loading in more than one dimension) and person
abilities with their posterior SDs (_SD columns).
parsEverything estimated, including the free parameters on their unconstrained scales and the row-level effective parameters.
personPosteriorEach person's mode and the precision (and,
with laplaceKeepCovariance, the covariance) of their posterior,
conditional on the item parameters.
abilityPriorThe ability prior's SDs, correlation (estimated
or fixed; see estimated_corr) and precision.
optimThe optimiser's result: logLik is the fitted
objective – the penalised Laplace (or refined) marginal, or the joint
log posterior for "map" – and grad and layout its
gradient by parameter block. Use logLik() for a likelihood.
laplaceStatusConvergence and its diagnosis, for either
estimator (the name is historical): converged and reason,
the convergence certificate, run-off items, and iteration-limit,
person-mode-failure, numerical-failure, frozen-effect,
approximate-gradient and covariance-retention flags. estimator and
marginal say which objective was fitted; for "map",
marginal_logLik is the marginal likelihood at the MAP estimates.
laplaceDiagnosticsWhen requested, one row per objective evaluation: objective, relative improvement, item and person RMS steps, item gradient, posterior SD, person convergence, timings, optimiser work and the strict criterion.
preparedThe prepared data the backend consumed: indices, response vectors, fixed-value maps and prior hyperparameters.
backend"laplace" or "map".
The frozen-effect flags, beta_frozen and its alias
frozen_effects, are TRUE only when personPreds were supplied
and their ability coefficients were held out of the optimised
parameter vector. Both estimators always estimate them, so these read
FALSE on any fit that has person predictors; a fit with none reports FALSE
too, because there is nothing that could be frozen. (Before this was
corrected the flag was set from the presence of person predictors alone,
so it was TRUE for precisely the fits that estimate the coefficients, and
print() wrongly announced that the effects had been held fixed.)
Row ordering. fitIRT sorts the data by person before
fitting, so most row-level objects are in that internal order. The two
per-response predictions users normally want, fit$pars$p (the
probability of the observed response) and fit$pars$pcorrect (the
probability of a correct response), are mapped back to the order of the
data passed in, so they can be indexed with the same row numbers used
for trainingRows; rows removed by dropPerfectScores are
NA. Every other row-level object – b_row, c_row,
d_row, eta_row, row_loadings, row_ability,
and the contents of fit$prepared – remains in internal order, because
the person-covariance routines pair those with fit$prepared$id. Use
fit$pars$originalRow, which gives the input row index of each
internal row, to move between the two.
#Generate some data (here 2pl model require(data.table) dat <- simIRT(Nsubs = 50,Nitems = 100,Nscales = 2, logitCMean = -10,logitCSD = 0,AMean = 1,ASD = .3, BMean=0,BSD = .5, AbilityMean = 0,AbilitySD = 1) #Fit by marginal maximum likelihood (the default), which integrates the #abilities out by a Laplace approximation. fit <- fitIRT(dat$dat,cores=2,score = 'score',id = 'id', scale = 'Scale',item = 'Item', pl=2) print(fit$personPars) print(fit$itemPars) #The same model by the joint posterior mode: same arguments, same output. fit_map <- fitIRT(dat$dat, cores = 2, pl = 2, marginalApprox = 'map') logLik(fit_map) # the model's marginal likelihood at the MAP estimates #Explicit multidimensional loading specification (2D example) #Rows/cols are aligned by names to item ids and scale ids. item_ids <- as.character(unique(dat$dat$Item)) scale_ids <- as.character(unique(dat$dat$Scale)) L <- matrix(NA_real_, nrow = length(item_ids), ncol = length(scale_ids), dimnames = list(item_ids, scale_ids)) L[1, ] <- c(0.8, 0.2) #fixed cross-loading L[2, 2] <- 0 #fixed zero loading fit_mirt <- fitIRT(dat$dat, pl = 2, cores = 1, loadings = L) head(fit_mirt$itemPars[, grep("^A(_|$)", names(fit_mirt$itemPars)), drop = FALSE])#Generate some data (here 2pl model require(data.table) dat <- simIRT(Nsubs = 50,Nitems = 100,Nscales = 2, logitCMean = -10,logitCSD = 0,AMean = 1,ASD = .3, BMean=0,BSD = .5, AbilityMean = 0,AbilitySD = 1) #Fit by marginal maximum likelihood (the default), which integrates the #abilities out by a Laplace approximation. fit <- fitIRT(dat$dat,cores=2,score = 'score',id = 'id', scale = 'Scale',item = 'Item', pl=2) print(fit$personPars) print(fit$itemPars) #The same model by the joint posterior mode: same arguments, same output. fit_map <- fitIRT(dat$dat, cores = 2, pl = 2, marginalApprox = 'map') logLik(fit_map) # the model's marginal likelihood at the MAP estimates #Explicit multidimensional loading specification (2D example) #Rows/cols are aligned by names to item ids and scale ids. item_ids <- as.character(unique(dat$dat$Item)) scale_ids <- as.character(unique(dat$dat$Scale)) L <- matrix(NA_real_, nrow = length(item_ids), ncol = length(scale_ids), dimnames = list(item_ids, scale_ids)) L[1, ] <- c(0.8, 0.2) #fixed cross-loading L[2, 2] <- 0 #fixed zero loading fit_mirt <- fitIRT(dat$dat, pl = 2, cores = 1, loadings = L) head(fit_mirt$itemPars[, grep("^A(_|$)", names(fit_mirt$itemPars)), drop = FALSE])
Registered against broom::glance() when broom is installed.
glanceIRT(x, ...)glanceIRT(x, ...)
x |
A fitted object from |
... |
Unused. |
A one-row data frame of backend, log-likelihood, degrees of freedom, AIC, BIC, sample sizes, convergence, reliability and held-out log loss.
The marginal log-likelihood of the persons a fit held out entirely (none
of their responses in trainingRows), each over all of their responses,
at the fitted parameters: the criterion improveModel() uses to compare
models. It integrates each person's ability by the fit's quadrature rule
around their posterior mode, and includes the ability prior's normalising
constant, so models with different numbers of dimensions or ability
variances compare correctly.
heldoutLogLik(fit, cores = 1L, nodes = NULL)heldoutLogLik(fit, cores = 1L, nodes = NULL)
fit |
A fit from |
cores, nodes
|
As for |
A list: loglik, persons, responses; NULL when no person
was held out entirely.
Scores the rows excluded by trainingRows against the item base rate, which
predicts each item's training success rate and ignores the person. That is
the fitted model with zero discrimination, so it lies inside the model's own
parameter space and is a fair floor.
heldoutMetrics(fit, eps = 1e-12)heldoutMetrics(fit, eps = 1e-12)
fit |
A fitted object from |
eps |
Numeric. Probability clamp for the log loss. |
A list of held-out response count, log loss, Brier score, AUC,
accuracy and the item-base-rate Brier score, or NULL when nothing was
held out.
Starting from a base model, repeatedly tests candidate changes at the
current fit (modificationTests()), refits the promising ones, and keeps
a change only if it improves the marginal likelihood of persons held out of
the fit entirely (heldoutLogLik()). Changes come in four kinds, each
refitted as a batch: covariates of ability (indicators, or a 3-df natural
spline), DIF on item intercepts or slopes for the flagged items along
person or response covariates, freed lower or upper asymptotes for the
flagged items, and group dimensions for item sets with local dependence
(each set's items load on a dimension of its own, uncorrelated with the
rest). A candidate must be significant after Benjamini-Hochberg within its
kind and large enough to matter (minEffect change in the probability of
a correct answer for DIF, minAsymptote for an asymptote, minGroupSD for
a group dimension's SD on the logit scale); a batch must raise the held-out
log-likelihood by at least minGain.
improveModel( dat, score = "score", id = "id", item = "Item", scale = "Scale", pl = 2L, personPreds = character(), personCovariates = character(), responseCovariates = character(), itemSets = character(), dif = c("B", "A"), difCovariates = NULL, asymptotes = c("lower", "upper"), holdout = 0.2, alpha = 0.05, minEffect = 0.03, minAsymptote = 0.05, minGroupSD = 0.3, minZ = stats::qnorm(0.95), minGain = 0, nsimDim = 19L, maxRounds = 3L, maxGroups = 2L, seed = 1L, cores = 1L, verbose = TRUE, fitArgs = list(laplaceRefine = "agq"), checkpoint = NULL, difImpact = TRUE, asymptotePooled = TRUE, partitions = TRUE, order = c("ability", "dimensions", "asymptotes", "dif"), commonEffects = TRUE, abilityTerms = list(), combineBydim = TRUE, gateCluster = NULL )improveModel( dat, score = "score", id = "id", item = "Item", scale = "Scale", pl = 2L, personPreds = character(), personCovariates = character(), responseCovariates = character(), itemSets = character(), dif = c("B", "A"), difCovariates = NULL, asymptotes = c("lower", "upper"), holdout = 0.2, alpha = 0.05, minEffect = 0.03, minAsymptote = 0.05, minGroupSD = 0.3, minZ = stats::qnorm(0.95), minGain = 0, nsimDim = 19L, maxRounds = 3L, maxGroups = 2L, seed = 1L, cores = 1L, verbose = TRUE, fitArgs = list(laplaceRefine = "agq"), checkpoint = NULL, difImpact = TRUE, asymptotePooled = TRUE, partitions = TRUE, order = c("ability", "dimensions", "asymptotes", "dif"), commonEffects = TRUE, abilityTerms = list(), combineBydim = TRUE, gateCluster = NULL )
dat |
Long data, one row per response. |
score, id, item, scale, pl
|
As for |
personPreds |
Person predictors in the base model's ability regression. |
personCovariates, responseCovariates, itemSets, dif, difCovariates, asymptotes
|
What to test; see |
holdout |
Share of persons held out to judge changes. |
alpha |
FDR level for candidates. |
minEffect, minAsymptote, minGroupSD
|
Smallest changes worth adding. |
minZ, minGain
|
A batch is kept when the held-out persons' log-
likelihood rises, compared person by person: by at least |
nsimDim |
Simulations for the null of the exploratory dimensions (0
turns them off); see |
maxRounds, maxGroups
|
Limits on rounds and on group dimensions. Group dimensions are added one per round, the strongest set first, so two dimensions need two rounds: until a real dimension is modelled, other sets look dependent too. |
seed |
For the holdout split. |
cores |
Threads. |
verbose |
Print progress. |
fitArgs |
Further |
checkpoint |
A directory to keep completed steps in, so that an
interrupted run resumes; |
difImpact, asymptotePooled, partitions
|
Offer the impact of DIF covariates, pooled asymptotes and partitions into correlated dimensions (see Details). |
order |
The kinds in the order they are screened and judged within a round: each of "ability", "dimensions", "asymptotes" and "dif" once (default in that order, the more general first; see Details). |
commonEffects |
Judge dimensions with the ability predictors'
effects common to them, and offer each DIF covariate's effect by
dimension as an alternative to its item DIF (see Details). |
abilityTerms |
A named list: for a covariate, the |
combineBydim |
Where a covariate's effect by dimension and its item DIF both pass their screens, offer a third alternative besides the two: the effect by dimension together with item DIF screened again at the model that has the effect. Item DIF flagged against a common effect covers a dimension's items wholesale where the gap differs by dimension, so without this a gap specific to one dimension with true DIF inside it can be described only as one or the other: on simulated data the item DIF won, took in the gap on many of the dimension's items, and the next round could not undo it. |
gateCluster |
Optional: a column of |
Within a round the kinds are taken in turn (order), the more general
first: ability, then dimensions, then asymptotes, then DIF (with the
impact of DIF covariates just before it). Each kind is screened and judged
at the model as it stands after the batches kept before it. So DIF is
judged with the dimensions in, where a group difference specific to one
subdomain can be the covariate's effect on that dimension rather than DIF
on its items (in one dimension it looks exactly like DIF, and was kept as
such in 90 to 100 per cent of simulated runs with none). An unmodelled
asymptote likewise looks like DIF between groups of different ability. A
covariate's effect on ability is in the model before DIF along it is
judged (DIF absorbs impact otherwise). Each kind is screened when its turn
comes, for itself alone.
DIF along each covariate (and parameter) is a batch of its own, the strongest first, so each covariate's DIF has to earn its place.
With difImpact, a DIF covariate whose effect on ability the model lacks
in any form (judged by the span of the ability predictors) first gets it,
as a batch of its own; a response covariate's within-person effect
included.
With asymptotePooled, the screened asymptotes have an alternative: the
asymptote free on every item, pooled by its prior.
Group dimensions go in one per round, the strongest first. With
partitions, an item-set column that covers every item (a partition,
such as subdomains) is offered as an alternative: its levels as
correlated ability dimensions.
With commonEffects, a dimension is judged on the dependence it
explains, not on group differences: the ability predictors keep one
effect common to a partition's dimensions and have none on a group
dimension. Freed by dimension, a covariate's effects would let a
dimension take in DIF on a few of its items. In the DIF stage each DIF
covariate's effect on ability is then also screened for differing by
dimension (DIF on all of a dimension's items at once), by a score test
of its own: a dimension's abilities take up most of such a gap, so the
item DIF screens barely see it. Where a covariate has both, the two are
alternatives; the next round screens both again. A covariate's effect is
carried by the predictor of that name, the terms added for it here, and
any abilityTerms names for it.
Of alternatives that pass the gate, the one with fewer terms is kept,
unless a larger one beats it on the held-out persons by the gate itself
(minGain, minZ, the larger against the smaller). Chosen by the larger
gain alone, near ties went to noise: DIF on all of a subdomain's items
beat the subdomain's own effect, 20 terms against 2, by under 3 nats out
of about 100. The comparison is in path (vs_smaller_gain,
vs_smaller_z).
The next round screens the result, for the kinds whose verdict could have changed: a kind is tried again only if it was kept, or a kind after it was, in the round before (a kind rejected in a round was already judged against every batch kept before it). The final model is refitted on all persons.
Selection uses the data, so the final model's estimates and standard errors are conditional on it: the held-out gain is the honest measure of what the changes are worth, not the in-sample fit.
On large data a run takes hours, so with checkpoint a directory keeps
each completed step (the base fit, each round's screens, each batch's
result and the fits kept) and a rerun resumes from them. A step is reused
only when the data size, holdout, settings and model specification it was
made under are identical; anything else is recomputed. Only completed steps
are written. Fits are kept uncompressed and can be gigabytes.
A bigIRT_improved object: fit (final model, all persons),
spec (the terms added), path (each batch tried: round, kind, terms,
held-out log-likelihood before and after, gain and its z, accepted,
seconds to fit and evaluate, for a larger alternative its gain and z
over the smaller, the batch fit's warnings, such as a fit that stopped
on unresolved person modes, and the training log-likelihood and free
parameters before and after, train_loglik_before,
train_loglik_after, df_before, df_after, train_persons: what a
likelihood ratio, AIC or BIC would judge the batch by; the free
parameters leave out item-specific coefficients whose covariate is zero
on all of the item's training responses), screens (each kind's tests, from the
screen it was last judged on), screens_all (every screen made, named by
step: a round's first screen round1_screens, then
round1_screens-<kind>), base_fit (the base model on the training persons),
holdout_persons, timing (seconds: base fit, each screen, final fit),
base (the settings a specification is built under: to refit spec
elsewhere, pass this rather than rebuilding it), fit_warnings (the
base and final fits' warnings).
modificationTests(), heldoutLogLik()
Evaluates 1D or multidimensional 4PL response curves under the bigIRT
parameterization
IRTcurve( A, B, C = 0, D = 1, theta = seq(-3, 3, 0.01), plot = TRUE, rescale = FALSE, add = FALSE, item = NULL, ... )IRTcurve( A, B, C = 0, D = 1, theta = seq(-3, 3, 0.01), plot = TRUE, rescale = FALSE, add = FALSE, item = NULL, ... )
A |
Numeric item-by-factor loading matrix, or a numeric vector for a single-factor model. |
B |
Numeric vector of item intercept/difficulty parameters. |
C |
Numeric vector of lower asymptotes. Defaults to 0. |
D |
Numeric vector of upper asymptotes. Defaults to 1. |
theta |
Numeric matrix of latent trait values (rows are evaluation points, columns are factors), or a numeric vector for a single-factor model. |
plot |
Logical; if |
rescale |
Logical; if |
add |
Logical; when plotting 1D curves, add to an existing plot. |
item |
Optional item index/indices to evaluate. |
... |
Additional graphical arguments passed to plotting functions. |
A numeric vector for a single item or a numeric matrix with rows
corresponding to theta points and columns to items.
Person parameters are integrated out of the marginal likelihood, so they
are not free parameters of it and are not counted; counting them would
penalise a model for the size of its sample. For a joint-MAP fit the
likelihood is that same marginal, evaluated at the MAP estimates (see
logLik.bigIRT_fit()), so the criteria compare fits by either estimator on
one scale. Effective and nominal degrees of freedom
are both reported, as are BIC on persons and on responses, since the two
answer different questions.
IRTic(fit, cores = 1L)IRTic(fit, cores = 1L)
fit |
A fitted object from |
cores |
Integer. Cores for the effective-parameter calculation. |
A data frame of criterion, degrees-of-freedom type, sample-size type, degrees of freedom and value.
Outfit is the mean squared standardised residual, and so is pulled about by unexpected responses far from an item's difficulty; infit weights by information and is the more stable of the two. Both are one pass over the responses.
itemFit(fit, training_only = TRUE)itemFit(fit, training_only = TRUE)
fit |
A fitted object from |
training_only |
Logical. Score training rows only. |
A data frame of item, response count, infit, outfit and a standardised outfit.
These are Rasch-family statistics. Their reference distributions are only well behaved for one- and two-parameter models, and should not be read as calibrated tests under a three- or four-parameter fit.
Observed information for each item's free parameters, with the standard
errors and effective parameter count that follow from it. With
priors = TRUE the fit is penalised, so these describe posterior curvature
rather than repeated sampling.
itemInformation( fit, cores = 1L, method = c("auto", "exact", "profile", "hessian"), person_tol = 1e-08, eps = 1e-04, max_blocks = 2000L, time_budget = 60 )itemInformation( fit, cores = 1L, method = c("auto", "exact", "profile", "hessian"), person_tol = 1e-08, eps = 1e-04, max_blocks = 2000L, time_budget = 60 )
fit |
A fitted object from |
cores |
Integer. Cores for the objective evaluations. |
method |
Character. |
person_tol |
Numeric. Person-mode tolerance for the differenced method. Must be far tighter than the fitting default, or the difference quotient measures frozen-mode curvature instead. |
eps |
Numeric. Step size for the difference quotients. |
max_blocks |
Integer. Refuse |
time_budget |
Numeric. Seconds |
An object of class bigIRT_iteminfo. P counts the parameter
types free on at least one item; a parameter an item has fixed (an
anchor through itemDat) is NA in every per-item entry below, and the
item's block covers only the parameters it has free.
P x P x Nitems array of likelihood information; for
"exact", the inverse of each item's covariance block, prior included.
Matching prior precision, zero without priors or
where information already carries it.
Inverse of each block; for "exact", each item's block
of the full inverse.
Nitems x P matrix of standard errors.
Effective parameters per item and block.
Nitems x P logical matrix, TRUE where the item has that
parameter free.
For "exact" on a fit with signed loadings
(signedLoadings in fitIRT()) only: the standard error of every free
loading's parameter, Nitems x Nscales, NA where the loading is fixed.
With cross-loadings free there is more than one loading per item, which
the per-item blocks do not describe.
The log-likelihood with the abilities integrated out, at the fitted item
parameters, with the item prior density removed and the ability prior's
normalising constants restored. For a joint-MAP fit (marginalApprox = "map"), the marginal likelihood of the same model evaluated at the MAP
estimates, by the approximation laplaceRefine selects, so that fits by
either estimator are compared on one scale.
## S3 method for class 'bigIRT_fit' logLik(object, effective = TRUE, cores = 1L, ...)## S3 method for class 'bigIRT_fit' logLik(object, effective = TRUE, cores = 1L, ...)
object |
A fitted object from |
effective |
Logical. Report effective rather than nominal degrees of freedom when the fit is penalised. |
cores |
Integer. Cores for the effective-parameter calculation. |
... |
Unused. |
An object of class logLik, with attributes df, nominal_df,
nobs (persons) and penalised.
The Laplace backend leaves a Gaussian posterior for each person, so draws
from it can be importance-weighted and handed to loo. Item parameters stay
at their mode, so the result is conditional on them; that is mild when
persons greatly outnumber the responses per item. Pareto k is the check that
matters, and held-out cross-validation is the better tool when it is large.
looIRT(fit, draws = 500L, persons = NULL, seed = NULL, cores = 1L)looIRT(fit, draws = 500L, persons = NULL, seed = NULL, cores = 1L)
fit |
A fitted object from |
draws |
Integer. Posterior draws per person. |
persons |
Integer. Optional person subsample, for datasets too large to hold a draws-by-responses matrix. |
seed |
Integer. Optional seed for the draws. |
cores |
Integer. Passed to |
An object of class loo.
Tests candidate changes to a fit at the fit itself, without fitting any alternative: covariates of ability, DIF on item intercepts or slopes along person or response covariates, per-item lower and upper asymptotes, and group dimensions shared by sets of items. Each comes with a one-step estimate of the change.
modificationTests( fit, dat, personCovariates = character(), responseCovariates = character(), itemSets = character(), dif = c("B", "A"), difCovariates = NULL, asymptotes = c("lower", "upper"), purify = TRUE, exploratory = TRUE, nsimDim = 19L, minSetItems = 3L, shape = FALSE, cores = 1L, byDimension = list() )modificationTests( fit, dat, personCovariates = character(), responseCovariates = character(), itemSets = character(), dif = c("B", "A"), difCovariates = NULL, asymptotes = c("lower", "upper"), purify = TRUE, exploratory = TRUE, nsimDim = 19L, minSetItems = 3L, shape = FALSE, cores = 1L, byDimension = list() )
fit |
A fit from |
dat |
The data the fit was made from (for covariates and item sets). |
personCovariates |
Columns of |
responseCovariates |
Columns of |
itemSets |
Columns of |
dif |
Item parameters tested for DIF: |
difCovariates |
The covariates tested for DIF, among
|
asymptotes |
|
purify |
Purify the DIF tests (recommended: it sets the anchors). |
exploratory |
Look for group dimensions in the scores alone (the
leading directions of residual covariance), as well as in |
nsimDim |
Data sets simulated from the fit for the null distribution of the leading eigenvalue. |
minSetItems |
Smallest item set tested for a group dimension. |
shape |
Also test each item's response function for curvature its
own parameters cannot express ( |
cores |
Threads. |
byDimension |
A named list: for each covariate, the ability
predictors that carry its effect, tested for an effect that differs by
dimension. Only meaningful at a fit that shares those effects across its
dimensions ( |
Ability covariates and DIF use scoreTest() (DIF purified, so it is
measured against anchors, with effect sizes). An asymptote fixed at c (or
d) is tested against freeing it: P is linear in c, so a response's score is
exact from its leave-one-out probability. A set of items is tested for a
shared person effect u ~ N(0, tau^2) on their linear predictors, the
variance-component score test (Lin, 1997) from each person's posterior
expectation of (sum g)^2 + sum h over the set; a significant one is local
dependence among the set's items, which a group dimension models.
Asymptote and group tests are one-sided.
A list of data.tables: ability, dif (with effect sizes),
asymptotes, groups, bydim (effects by dimension); each with
p-values adjusted by Benjamini-Hochberg (p_fdr) within its kind; and
dimensions, the exploratory eigenpairs with their null draws.
Normalise item response theory (IRT) parameters.
normaliseIRT( B, Ability, A, normbase = "Ability", normaliseScale = 1, normaliseMean = 0, robust = TRUE, AbilitySD = NULL, AbilityMean = NULL )normaliseIRT( B, Ability, A, normbase = "Ability", normaliseScale = 1, normaliseMean = 0, robust = TRUE, AbilitySD = NULL, AbilityMean = NULL )
B |
Vector of item difficulty parameters. |
Ability |
Vector of persons' ability parameters. |
A |
Vector of item discrimination parameters. |
normbase |
The base from which the normalisation should be calculated. Can be 'Ability' or 'B'. |
normaliseScale |
The scale to normalise to. |
normaliseMean |
The mean to normalise to. The default is 0 for the
supported |
robust |
If TRUE, the location and scale come from the median and the
interquartile range, the latter converted to a standard deviation
(divided by 1.349, its value for a normal distribution). Until October
2026 the interquartile range itself was set to |
AbilitySD, AbilityMean
|
Optional latent standard deviation and mean of
the solution, used in place of the spread and centre of |
A list containing the normalised A, B, and Ability parameters, and
for normbase 'Ability' or 'B' the center and scale
of the transform: the normalised abilities are
(Ability - center) / scale + normaliseMean.
B <- rnorm(100,2,1) Ability <- rnorm(500,3,.5) A <- rnorm(100,1.4,.05) normaliseIRT(B, Ability, A, normbase='B')B <- rnorm(100,2,1) Ability <- rnorm(500,3,.5) A <- rnorm(100,1.4,.05) normaliseIRT(B, Ability, A, normbase='B')
Applies a curve-preserving affine transform to a multidimensional IRT solution so that the latent ability distribution is centered and whitened, with optional orthogonal alignment to a reference loading matrix.
normaliseMIRT( B, Ability, A, AbilityCorr = NULL, normaliseScale = 1, normaliseMean = 0, jitter = 1e-08, referenceA = NULL, align = c("none", "orthogonal"), AbilitySD = NULL, AbilityMean = NULL )normaliseMIRT( B, Ability, A, AbilityCorr = NULL, normaliseScale = 1, normaliseMean = 0, jitter = 1e-08, referenceA = NULL, align = c("none", "orthogonal"), AbilitySD = NULL, AbilityMean = NULL )
B |
Numeric vector of item intercept/difficulty parameters. |
Ability |
Numeric matrix of person abilities with rows corresponding to persons and columns to latent factors. Its mean and covariance define the transform, so it should represent the latent distribution: true or generating abilities, or draws from the fitted posterior. Point estimates (MAP, EAP) are shrunk toward the prior mean, so their spread understates the latent scale by roughly the square root of the reliability, and the loadings come out flattened by the same factor – about a fifth at ten responses per person. Solutions that already share an identification (the same fixed latent distribution and a confirmatory loading pattern) need no transform at all. |
A |
Numeric item-by-factor loading matrix. |
AbilityCorr |
Optional latent correlation matrix. If omitted, the
correlation is estimated from |
normaliseScale |
Numeric scalar giving the target latent SD after whitening. Defaults to 1. |
normaliseMean |
Numeric scalar or vector giving the target latent mean after normalization. Defaults to 0. |
jitter |
Small positive constant added for numerical stability. |
referenceA |
Optional reference loading matrix used for orthogonal Procrustes alignment. |
align |
Character string, either |
AbilitySD, AbilityMean
|
Optional latent standard deviations and means,
one per factor, used in place of the spread and centre of |
A list containing normalized A, B, Ability, and associated
affine transform pieces (center, chol_cov, inv_chol, AbilityCorr,
sign, and rotation).
Builds a posterior precision matrix for each person by combining a prior
precision matrix with row-wise Fisher information contributions. The intended
input is the row-level moderated parameter state a fit reports
(fit$rowEffective):
a current person mean matrix theta_mean
row-level effective difficulties b
row-level effective lower and upper asymptotes c and d
row-level effective loading vectors, supplied either densely or in sparse row form
personCovarianceMatrices( id, theta_mean, b, loadings, c = NULL, d = NULL, prior_precision = NULL, jitter = 1e-08, max_attempts = 8, return_precision = TRUE )personCovarianceMatrices( id, theta_mean, b, loadings, c = NULL, d = NULL, prior_precision = NULL, jitter = 1e-08, max_attempts = 8, return_precision = TRUE )
id |
A vector of person ids with one entry per observation row. |
theta_mean |
A numeric |
b |
Numeric vector of row-level effective difficulties. |
loadings |
Either an |
c |
Numeric vector of row-level lower asymptotes. Defaults to all zeros. |
d |
Numeric vector of row-level upper asymptotes. Defaults to all ones. |
prior_precision |
Either |
jitter |
Initial diagonal jitter added before Cholesky factorisation. |
max_attempts |
Maximum number of jitter expansions before failing. |
return_precision |
Logical. If |
For each response row attached to person , the function
computes
where is the prior precision for person , is
the row-level effective loading vector, and
is the Bernoulli Fisher-information weight. This is stable for 2PL, 3PL, 4PL, and sparse multidimensional loadings.
The embedded C++ backend returns the posterior precision, its lower Cholesky
factor, and the implied covariance matrix for each person. The pure R version
personCovarianceMatrices_R mirrors the same calculations for
sanity checks.
A list with:
covariancePosterior covariance array with dimensions
K x K x Nsubs.
precisionPosterior precision array with dimensions
K x K x Nsubs.
precision_cholLower Cholesky factor of the posterior precision for each person.
chol_jitter_usedThe diagonal jitter needed for each person-specific factorisation.
id_levelsUnique person ids corresponding to the third array dimension.
backendEither "cpp" or "R".
# Two-dimensional row-level example with one cross-loading row. theta_mean <- rbind( c(-0.3, 0.4), c(0.6, -0.2) ) colnames(theta_mean) <- c("math", "verbal") row_loadings <- rbind( c(1.2, 0.0), c(0.8, 0.3), c(0.0, 1.1), c(0.5, 0.6) ) ids <- c("p1", "p1", "p2", "p2") b <- c(-0.5, 0.1, 0.0, -0.2) cpar <- rep(0, length(ids)) dpar <- rep(1, length(ids)) sparse_loadings <- rowLoadingsToSparse(row_loadings) out_cpp <- personCovarianceMatrices( id = ids, theta_mean = theta_mean, b = b, c = cpar, d = dpar, loadings = sparse_loadings, prior_precision = diag(2) ) out_r <- personCovarianceMatrices_R( id = ids, theta_mean = theta_mean, b = b, c = cpar, d = dpar, loadings = sparse_loadings, prior_precision = diag(2) ) max(abs(out_cpp$covariance - out_r$covariance)) out_cpp$covariance[, , "p1"]# Two-dimensional row-level example with one cross-loading row. theta_mean <- rbind( c(-0.3, 0.4), c(0.6, -0.2) ) colnames(theta_mean) <- c("math", "verbal") row_loadings <- rbind( c(1.2, 0.0), c(0.8, 0.3), c(0.0, 1.1), c(0.5, 0.6) ) ids <- c("p1", "p1", "p2", "p2") b <- c(-0.5, 0.1, 0.0, -0.2) cpar <- rep(0, length(ids)) dpar <- rep(1, length(ids)) sparse_loadings <- rowLoadingsToSparse(row_loadings) out_cpp <- personCovarianceMatrices( id = ids, theta_mean = theta_mean, b = b, c = cpar, d = dpar, loadings = sparse_loadings, prior_precision = diag(2) ) out_r <- personCovarianceMatrices_R( id = ids, theta_mean = theta_mean, b = b, c = cpar, d = dpar, loadings = sparse_loadings, prior_precision = diag(2) ) max(abs(out_cpp$covariance - out_r$covariance)) out_cpp$covariance[, , "p1"]
This function mirrors personCovarianceMatrices but performs the
row-wise precision accumulation and per-person matrix inversions in R. It is
intended for sanity checks against the embedded C++ implementation.
personCovarianceMatrices_R( id, theta_mean, b, loadings, c = NULL, d = NULL, prior_precision = NULL, jitter = 1e-08, max_attempts = 8, return_precision = TRUE )personCovarianceMatrices_R( id, theta_mean, b, loadings, c = NULL, d = NULL, prior_precision = NULL, jitter = 1e-08, max_attempts = 8, return_precision = TRUE )
id |
A vector of person ids with one entry per observation row. |
theta_mean |
A numeric |
b |
Numeric vector of row-level effective difficulties. |
loadings |
Either an |
c |
Numeric vector of row-level lower asymptotes. Defaults to all zeros. |
d |
Numeric vector of row-level upper asymptotes. Defaults to all ones. |
prior_precision |
Either |
jitter |
Initial diagonal jitter added before Cholesky factorisation. |
max_attempts |
Maximum number of jitter expansions before failing. |
return_precision |
Logical. If |
A list with posterior covariance; and if
return_precision=TRUE, also precision and
precision_chol arrays.
Plot Laplace diagnostics
plotLaplaceDiagnostics(fit, logGrad = TRUE, showTiming = TRUE)plotLaplaceDiagnostics(fit, logGrad = TRUE, showTiming = TRUE)
fit |
A fitted |
logGrad |
Whether to plot the item-step gradient norm on a log10 scale. |
showTiming |
Whether to include timing and stability panels. |
Invisibly returns the diagnostic data frame used for plotting.
Empirical reliability compares the spread of the estimates against that spread plus the average error variance; marginal reliability compares the average error variance against the prior variance. They disagree when the estimates are shrunk, so both are reported.
reliability(fit)reliability(fit)
fit |
A fitted object from |
A data frame with one row per latent dimension.
A self-contained HTML report: convergence, the item table, information and reliability, person and item coverage, item fit, the worst-fitting response curves, and held-out performance. Everything in it comes from the exported functions, so it is a convenience rather than a second implementation.
reportIRT( fit, file = "bigIRT-report.html", title = "bigIRT model report", method = "profile", max_icc = 9L, cores = 1L, quiet = TRUE )reportIRT( fit, file = "bigIRT-report.html", title = "bigIRT model report", method = "profile", max_icc = 9L, cores = 1L, quiet = TRUE )
fit |
A fitted object from |
file |
Character. Output path. |
title |
Character. Report title. |
method |
Character. Passed to |
max_icc |
Integer. Worst-fitting items to draw curves for. |
cores |
Integer. Cores for the information calculation. |
quiet |
Logical. Passed to |
The output path, invisibly.
Converts an matrix of effective row loadings into a
compact sparse representation suitable for fast row-wise accumulation in C++.
Each row can correspond to a fully moderated loading vector after any item or
person covariate effects have already been applied.
rowLoadingsToSparse(loadings, tol = 0)rowLoadingsToSparse(loadings, tol = 0)
loadings |
A numeric matrix with one row per observation and one column per latent dimension. |
tol |
Values with absolute magnitude less than or equal to |
A list with:
row_ptrInteger vector of length Nobs + 1. Entries mark
the start of each row in load_idx and load_val.
load_idx1-based latent-dimension indices for non-zero loadings.
load_valNon-zero loading values.
n_dimNumber of latent dimensions.
Each response's contribution to the score of the marginal likelihood in
its item's parameters, with the matching observed information, and each
person's contribution to the score in the ability distribution's mean. They
are what score-based tests of differential item functioning and of ability
covariates are built from (see scoreTest()), and they can be summed by any
grouping for other diagnostics.
scoreContributions( fit, nodes = NULL, information = TRUE, cores = 1L, exclude = NULL )scoreContributions( fit, nodes = NULL, information = TRUE, cores = 1L, exclude = NULL )
fit |
A fit from |
nodes |
Integer. Quadrature nodes per dimension. Default: the fit's own
rule if it was refined by quadrature, otherwise 9, 7 and 5 for one to
three dimensions and the anchored pairwise rule beyond. |
information |
Logical. Also return each response's observed information in its item's slots. Default TRUE. |
cores |
Integer. Threads for the person-level kernels. |
exclude |
Optional item labels whose responses are held out of every
person's posterior – the anchoring step of DIF purification (see
|
A person's marginal score is the posterior expectation of the
complete-data score (the Fisher identity), taken here by adaptive
Gauss-Hermite quadrature centred at the person's Laplace mode; the
information is the Louis identity on the same nodes. Under the fitted model
these contributions have mean zero for every person, conditionally on the
person's covariates, which is the property score-based tests rest on. The
plug-in score at an estimated ability does not have it: the ability
estimate's own error leaves a residual pattern in ability, and when a
covariate is related to ability that pattern is ordered by the covariate.
nodes = 1 returns that plug-in score, at the posterior mode, for
comparison.
The scores are those of the quadrature marginal, so they sum to (nearly)
zero over an item's responses only when the item parameters sit at that
marginal's optimum. A fit that ended on the Laplace objective (the default
for a one-dimensional 2PL) is close to it but not at it; scoreTest()
allows for the gap, but with few responses per person a fit refined with
laplaceRefine = "agq" is the cleaner basis. Measured with ten items per
person, 5,000 persons and a covariate related to ability: refining shrank
the item score sums fifteenfold and moved the LM test's false-positive rate
from 5.3 to 4.0 per cent (600 tests each).
Scores are in the coordinates the model is estimated in, which are also the
ones item covariate effects act on: B is the intercept in
(positive is harder); A the loading's raw
coordinate (softplus link, or the loading itself when signed); C and D
the logits of the half-range asymptote links.
An object of class bigIRT_scores, a list with
rowsA data.table, one row per training response: row (its
row in the data passed to fitIRT()), id, Item, internal indices
person and item, the response y, the score in each free parameter
type (B, A or A1, A2, ..., C, D; zero where the response's
item has that parameter fixed), eta, the score in the linear
predictor (for the 2PL, the response minus its posterior-expected
probability), ppred, the probability of a correct response given the
person's other responses (the row's leave-one-out posterior
predictive), and, with information, the observed information entries
I.<a>.<b>.
personsA data.table per person: id, person, the posterior
mean and SD of (base) ability on each dimension, the score in the
ability mean (mu, mu1, ...) and its information Imu.<k>.<l>.
slots, K, rule, item_free, item_labels, id_name,
item_name
Bookkeeping used by scoreTest().
Tests whether item parameters depend on a covariate (differential item
functioning, uniform or not), or whether ability does, using only the
fitted model's score contributions (scoreContributions()). No model is
refitted, so any number of covariates can be screened after one large fit.
scoreTest( fit, covariates, parameters = "B", form = c("auto", "linear", "spline", "factor", "fluctuation"), by = "item", items = NULL, df = 3L, dims = NULL, level = c("auto", "person", "row"), ngrid = 50L, trim = 0.1, nsim = 1000L, seed = NULL, minN = 20L, purify = FALSE, purifyAlpha = 0.05, purifyMaxIter = 5L, purifyMinAnchor = 0.1, information = c("expected", "observed", "opg"), adjust = c("auto", "none"), adjustDf = 3L, adjustMethod = c("fast", "full"), effects = TRUE, nodes = NULL, cores = 1L, contributions = NULL )scoreTest( fit, covariates, parameters = "B", form = c("auto", "linear", "spline", "factor", "fluctuation"), by = "item", items = NULL, df = 3L, dims = NULL, level = c("auto", "person", "row"), ngrid = 50L, trim = 0.1, nsim = 1000L, seed = NULL, minN = 20L, purify = FALSE, purifyAlpha = 0.05, purifyMaxIter = 5L, purifyMinAnchor = 0.1, information = c("expected", "observed", "opg"), adjust = c("auto", "none"), adjustDf = 3L, adjustMethod = c("fast", "full"), effects = TRUE, nodes = NULL, cores = 1L, contributions = NULL )
fit |
A fit from |
covariates |
The covariates to test. Person-level: a data frame with
the fit's id column (or |
parameters |
Which parameters to test: any of |
form |
|
by |
|
items |
Optional item labels to test (default all). |
df |
Degrees of freedom of the spline basis. |
dims |
For |
level |
|
ngrid, trim, nsim
|
Fluctuation tests: maximum number of breakpoints
(blocks of persons in covariate order), the trimming fraction for
|
seed |
Optional seed for the simulated p-values. |
minN |
Minimum number of responses for an item to be tested. |
purify, purifyAlpha, purifyMaxIter
|
Iterative purification against DIF contamination (see above), the adjusted-p threshold for flagging, and the maximum number of anchoring rounds. Item tests by item only. |
purifyMinAnchor |
The fewest items purification may leave as anchors:
a share of the tested items when below 1 (default .1), a count
otherwise. When the flagged set would leave fewer, the items with the
least evidence of DIF (largest p) are kept as anchors instead – a
rank-based constant anchor (Woods, 2009; Kopf, Zeileis & Strobl, 2015)
– and a warning of class |
information |
Which information the item tests use.
|
adjust, adjustDf
|
|
adjustMethod |
How the added covariate's coefficients and the
residual ability SD are estimated. |
effects |
Report DIF effect sizes (parametric forms). Each response's
score is the score of a Bernoulli given the person's other responses, so
the derivative of its predicted probability in the item's parameters is
exact; applied to the one-step DIF estimate it gives the response's
first-order change in the probability of a correct answer at the
person's own ability. These are averaged per item ( |
nodes, cores
|
Passed to |
contributions |
Optional: |
Two families of test are available.
form = "linear", "spline", "factor")The score
(Lagrange multiplier) test of adding the covariate, through the chosen
basis, to the tested parameters. Exact chi-square reference. Each test
also gives the one-step estimate of the coefficients it tests – for
items, what fitIRT() with the covariate in BitemPreds (or
AitemPreds, ...) and itemSpecificBetas = TRUE would estimate, on the
same coordinates; for ability, what it would estimate with the
covariate in personPreds – with a standard error.
form = "fluctuation")The nonparametric CUSUM tests
of Merkle and Zeileis (double maximum DM, Cramer-von Mises CvM,
maxLM), which order persons by the covariate and need no functional
form. The process's covariance is computed from the information
accrued between breakpoints and the p-values are simulated from it,
so they stay valid when information does not accrue uniformly along
the covariate (impact does that). p_DM_bb is the classical Brownian
bridge p-value, for comparison.
In both, each item's own other parameters are projected out exactly (Neyman's C(alpha) construction), so testing one parameter while the others are estimated is accounted for, and the small pull of the item priors on the fit is too.
Impact. A covariate related to ability has to be in the ability model
for its DIF tests to be valid; otherwise every item inherits the
unmodelled ability difference. When fit is a fit and the covariate is not
among its personPreds, adjust = "auto" (the default) puts it there
after the fact: a natural spline of it (adjustDf degrees of freedom), or
indicators for a factor, centred, enters the ability regression, its
coefficients are estimated with the item parameters held, and the
contributions are recomputed under that model before testing. A
response-level covariate enters per response, so ability may also change
with it within person (age at the response, say). The item parameters stay
as the fit estimated them, without the covariate; each item's test projects
out the resulting discrepancy in its own parameters. adjust = "none"
tests against the fit as it is, and then warns when a person-level
covariate is related to ability but absent from the model.
The same is true of the uniform part of DIF that every item shares: it is
indistinguishable from an ability difference, and DIF is measured relative
to it.
Purification. When several items have DIF in the same direction, their
DIF pulls every person's ability posterior (and the ability model's
coefficient on the covariate) towards explaining it, and the clean items
then show DIF the other way. purify = TRUE screens, flags the items whose
Benjamini-Hochberg adjusted p is below purifyAlpha, recomputes the score
contributions with the flagged items' responses left out of every person's
posterior and the ability coefficients re-estimated on the rest
(exclude in scoreContributions()), and retests the rest against that
anchor; flagged items are retested against the same anchor, each response
scored against the anchor posterior with its own likelihood added, in the
same pass. It repeats until the flagged set stops changing. Only the person side is
recomputed, so this needs the fit, not its score contributions, but no
refit.
Ability. parameters = "Ability" tests the covariate as a predictor of
ability (on every dimension, or those in dims), with the ability mean
and the fit's existing person predictors projected out.
An object of class bigIRT_scoretest: a list with tests, a
data.table with one row per covariate and item (or group): the number of
responses n, the statistic(s), degrees of freedom and p-values (with
purify, also whether the item ended as an anchor and the stage its
test comes from), with
Benjamini-Hochberg (p_fdr) and Holm (p_holm) adjustments within each
covariate; and, for the parametric forms, coefficients, a data.table of
one-step estimates (estimate), standard errors and z values per tested
parameter and basis column; and, when a covariate was added to the
ability model (adjust), adjustment: its basis terms' estimated
coefficients, the re-estimated ability SD against the fit's, and the
iterations taken and whether they converged (a warning is given if not).
With effects: effects, per item and contrast (a factor level against
the reference level; a continuous covariate's 90th against its 10th
percentile over responses), the mean change in the probability of a
correct answer over the item's responses at equal ability, signed (dP)
and unsigned (dP_abs), first-order in the DIF estimate. They are
relative to the scale the other items set: with purify, the anchors;
without, all items, which absorb any net DIF into the estimated impact.
With purify and a person-level covariate (one-dimensional models), also
dtf, the test-level effect of the flagged items per level or covariate
quintile, relative to the reference group (the reference level, or the
middle quintile): the mean change in a person's expected number correct
over the items they answered (dT_flagged), and the ability shift that
would change their expected score as much (dtheta_flagged) – the bias
DIF puts into a person's ability estimate when scored with these item
parameters, to first order. Without anchors there is no test-level
effect to report: with the covariate's ability effect estimated freely,
the DIF effects of all items sum to about zero for each group.
Simulate IRT data
simIRT( Nsubs = 100, Nitems = 200, Nscales = 1, NitemsAnswered = Nitems, ASD = 0, AMean = 1, BSD = 1, BMean = 0, logitCSD = 1, logitCMean = -2, logitDSD = 0, logitDMean = 20, AbilitySD = 1, AbilityMean = 0, AbilityCorr = diag(1, Nscales), itemPreds = NA, AitemPredEffects = NA, BitemPredEffects = NA, logitCitemPredEffects = NA, logitDitemPredEffects = NA, personPreds = NA, AbilityPredEffects = NA, mirt = FALSE, loadingSparsity = 0.3, primaryScale = NA, loadings = NA, crossLoadingSD = 0.15, returnRowLoadings = TRUE )simIRT( Nsubs = 100, Nitems = 200, Nscales = 1, NitemsAnswered = Nitems, ASD = 0, AMean = 1, BSD = 1, BMean = 0, logitCSD = 1, logitCMean = -2, logitDSD = 0, logitDMean = 20, AbilitySD = 1, AbilityMean = 0, AbilityCorr = diag(1, Nscales), itemPreds = NA, AitemPredEffects = NA, BitemPredEffects = NA, logitCitemPredEffects = NA, logitDitemPredEffects = NA, personPreds = NA, AbilityPredEffects = NA, mirt = FALSE, loadingSparsity = 0.3, primaryScale = NA, loadings = NA, crossLoadingSD = 0.15, returnRowLoadings = TRUE )
Nsubs |
Integer. Number of subjects. |
Nitems |
Integer. Number of items per scale. |
Nscales |
Integer. Number of scales. |
NitemsAnswered |
Integer (or length- |
ASD |
Numeric. SD of simulated item discrimination values ( |
AMean |
Numeric. Mean of simulated item discrimination values ( |
BSD |
Numeric. SD of simulated item difficulty values ( |
BMean |
Numeric. Mean of simulated item difficulty values ( |
logitCSD |
Numeric. SD of simulated guessing values on logit scale. |
logitCMean |
Numeric. Mean of simulated guessing values on logit scale. |
logitDSD |
Numeric. SD of simulated upper asymptote values on logit scale. |
logitDMean |
Numeric. Mean of simulated upper asymptote values on logit scale. |
AbilitySD |
Numeric. SD of simulated person abilities. |
AbilityMean |
Numeric. Mean of simulated person abilities. |
AbilityCorr |
Matrix. Correlation matrix for the latent abilities,
used when |
itemPreds |
Optional matrix/data frame of item-level predictors. Rows should align with items. |
AitemPredEffects |
Optional numeric matrix/vector of effects of
|
BitemPredEffects |
Optional numeric matrix/vector of effects of
|
logitCitemPredEffects |
Optional numeric matrix/vector of effects of
|
logitDitemPredEffects |
Optional numeric matrix/vector of effects of
|
personPreds |
Optional matrix/data frame of person-level predictors. Rows should align with subjects. |
AbilityPredEffects |
Optional matrix of effects of |
mirt |
Logical. If |
loadingSparsity |
Numeric in |
primaryScale |
Optional integer vector of length |
loadings |
Optional numeric |
crossLoadingSD |
Numeric. SD of sampled non-primary loading values when
|
returnRowLoadings |
Logical. If |
A list with:
Matrix of true person abilities (Nsubs x Nscales).
Matrix of true item discriminations (Nitems x Nscales).
Matrix/vector of true item difficulties. Matrix in legacy mode,
vector in mirt=TRUE mode.
The two modes use different parameterisations, and B is not on the
same scale as the B that fitIRT() reports. Legacy mode generates
, so B is a
difficulty in the classical sense. mirt = TRUE generates
, so B is an
intercept, which is the convention fitIRT() estimates and reports.
To compare a legacy simulation against a fit, convert first: the
generating intercept is A * B. Comparing the two unconverted costs an
error of , which cancels in mean bias, grows with the size
of the difficulty, and does not shrink as the sample grows, so it looks
like a calibration failure rather than a units error. compareIRTmodels()
and extractMIRTpars() handle the conversion for you.
Matrix/vector of true item guessing parameters. Matrix in legacy
mode, vector in mirt=TRUE mode.
Matrix/vector of true item upper asymptote parameters. Matrix in legacy
mode, vector in mirt=TRUE mode.
Long-format response data as a data.table.
sim <- simIRT(Nsubs = 100, Nitems = 40, Nscales = 1, ASD = .2, BSD = .8) head(sim$dat)sim <- simIRT(Nsubs = 100, Nitems = 40, Nscales = 1, ASD = .2, BSD = .8) head(sim$dat)
Fisher information in each response, summed over items, with the conditional standard error of measurement that follows from it.
testInformation(fit, theta = seq(-4, 4, 0.05), scale = NULL, items = NULL)testInformation(fit, theta = seq(-4, 4, 0.05), scale = NULL, items = NULL)
fit |
A fitted object from |
theta |
Numeric vector of ability points. |
scale |
Optional scale name to restrict to. |
items |
Optional item index to restrict to. |
An object of class bigIRT_information, carrying theta,
item_information, test_information and sem.
One row per item parameter, with a standard error and Wald interval when
asked. Standard errors are carried onto the reported parameter scale by the
delta method, since discrimination is estimated as a softplus pre-image and
the asymptotes as logits; a signed loading (signedLoadings in fitIRT())
is estimated as itself and needs none. On a fit with signed loadings every
free cross-loading also gets a row, term A_<scale>, whose standard error
comes from the exact covariance (method = "exact"). A parameter fixed
through itemDat is not estimated, so its standard error and interval are
NA. Registered against broom::tidy() when broom is installed.
tidyIRT( x, conf.int = FALSE, conf.level = 0.95, method = if (is.null(x$laplaceStatus$certificate$covariance$items)) "profile" else "exact", cores = 1L, ... )tidyIRT( x, conf.int = FALSE, conf.level = 0.95, method = if (is.null(x$laplaceStatus$certificate$covariance$items)) "profile" else "exact", cores = 1L, ... )
x |
A fitted object from |
conf.int |
Logical. Compute standard errors and intervals. |
conf.level |
Numeric. Interval coverage. |
method |
Character. Passed to |
cores |
Integer. Cores for the information calculation. |
... |
Unused. |
A data frame of item, term and estimate and, when requested, standard error and interval.
Computes the WLE and SE for each subject and scale in a bigIRT model.
wleIRT(fit)wleIRT(fit)
fit |
A fitted object returned by |
A list with:
Matrix of weighted likelihood estimates by subject and scale.
Matrix of approximate standard errors for wle.
sim <- simIRT(Nsubs = 60, Nitems = 20, Nscales = 1) fit <- fitIRT(sim$dat, pl = 2, cores = 1, dropPerfectScores = FALSE) wle <- wleIRT(fit) str(wle)sim <- simIRT(Nsubs = 60, Nitems = 20, Nscales = 1) fit <- fitIRT(sim$dat, pl = 2, cores = 1, dropPerfectScores = FALSE) wle <- wleIRT(fit) str(wle)