Conditional Item Infit MSQ for Multiply Imputed Data
Source:R/conditional_infit_mi.R
RMitemInfitMI.RdExtends RMitemInfit to work with multiply imputed datasets
produced by the mice package. Computes conditional infit MSQ on each
imputed dataset and pools the results using Rubin's rules.
Arguments
- mids_object
A
midsobject (multiply imputed dataset) as returned bymice::mice(). Each completed dataset must contain only the item response columns to be analysed (i.e., no ID or grouping variables). Items must be scored starting at 0 (non-negative integers).- cutoff
Optional. Default
NULL(no cutoff applied). Can be:The return value of
RMitemInfitCutofforRMitemInfitCutoffMI(a list with$item_cutoffs): the data.frame is extracted automatically and metadata is included in the kable caption.The
$item_cutoffsdata.frame directly: must have columnsItem,infit_low, andinfit_high. When provided, adds columnsInfit_low,Infit_high, andFlaggedto the result.Flaggedis a character column labelling the misfit direction:"overfit"(pooled infit below the range),"underfit"(above), or""(within range).
- output
Character string controlling the return value. Either
"kable"(default) for a formattedknitr::kable()table, or"dataframe"for the underlying data.frame.- sort
Optional character string. When
sort = "infit", rows are sorted byInfit_MSQin descending order before output.
Value
If
output = "kable": aknitr_kableobject (plain text table viaformat = "pipe") with columns "Item", "Infit MSQ", "Infit SE", "Relative location", and a caption noting the number of imputations and complete cases. Whencutoffis provided, columns "Infit low", "Infit high", and "Flagged" are also included.If
output = "dataframe": a data.frame with columnsItem,Infit_MSQ,Infit_SE, andRelative_location. Whencutoffis provided, columnsInfit_low,Infit_high, andFlaggedare also included (inserted afterInfit_SE, beforeRelative_location).Flaggedis a character column ("overfit"/"underfit"/""), not the previous logical.
Details
For each of the m imputed datasets, the function:
Fits a Rasch model by CML via
psychotools::pcmodel()(a dichotomous item is a 2-category partial credit model), consistent withRMitemInfitand the rest of the package.Computes conditional infit MSQ and its standard error via
iarm::out_infit().Computes item locations (mean of the grand-mean-centred CML Andrich thresholds) and the mean WLE person location.
The per-imputation estimates are then pooled using Rubin's rules:
- Pooled MSQ
The mean of the
minfit MSQ point estimates.- Within-imputation variance
The mean of the
msquared standard errors.- Between-imputation variance
The sample variance of the
mpoint estimates.- Total variance
Within + (1 + 1/m) * Between.
- Pooled SE
The square root of the total variance.
Relative item location is the mean of per-imputation relative locations (item location minus sample mean person location).
Caveat on the pooled SE. The within-imputation variance is the
squared conditional infit SE from iarm::out_infit(). Müller (2020) showed
that this asymptotic SE is an unreliable measure of uncertainty for the
conditional infit statistic; Rubin's pooled SE inherits that limitation, so
the Infit_SE/Infit SE column should be read as an approximate indication
of imputation-related variability rather than a trustworthy inferential
standard error. For item misfit decisions, prefer the simulation-based
cutoffs from RMitemInfitCutoffMI.
Imputed datasets that cause model convergence failures are dropped with a warning. If all imputations fail, the function stops with an error. At least two successful imputations are required to estimate between-imputation variance.
The mice and iarm packages must be installed (they are in Suggests, not
Imports).
References
Müller, M. (2020). Item fit statistics for Rasch analysis: Can we trust them? Journal of Statistical Distributions and Applications, 7(5). doi:10.1186/s40488-020-00108-7
Examples
# \donttest{
if (requireNamespace("mice", quietly = TRUE) &&
requireNamespace("iarm", quietly = TRUE) &&
requireNamespace("ggdist", quietly = TRUE)) {
# Create example data with ~10% MCAR missingness
set.seed(42)
mat <- matrix(sample(0:1, 200 * 8, replace = TRUE), nrow = 200, ncol = 8)
mat[sample(length(mat), round(0.10 * length(mat)))] <- NA
sim_data <- as.data.frame(mat)
colnames(sim_data) <- paste0("Item", 1:8)
# mice's ordinal method (`polr`) requires the items to be ordered
# factors, so code them as such before imputing. RMitemInfitMI()
# converts the completed factors back to numeric internally.
sim_data[] <- lapply(sim_data, function(x) factor(x, ordered = TRUE))
# Impute (use more imputations, e.g. m = 5+, in real analyses)
imp <- mice::mice(sim_data, m = 2, method = "polr", seed = 123,
printFlag = FALSE)
# Pooled infit table (no cutoffs)
RMitemInfitMI(imp)
# With simulation-based cutoffs
# (use more iterations, e.g. 250+, in real analyses)
cutoff_mi <- RMitemInfitCutoffMI(imp, iterations = 50, parallel = FALSE,
seed = 42)
RMitemInfitMI(imp, cutoff = cutoff_mi)
# As data.frame
df <- RMitemInfitMI(imp, cutoff = cutoff_mi, output = "dataframe")
}
# }