| Title: | A Friendly Workflow and Reporting Layer for 'mirt' |
|---|---|
| Description: | Extends the 'mirt' package for item response theory with tidy outputs, 'ggplot2' graphics (trace lines, information, Wright maps, fit and local dependence plots), an automatic model selection assistant, plain-language interpretation of results, item health cards, one-call HTML reports, a point-and-click 'shiny' workbench that exports reproducible code, and a joint hierarchical model for responses and response times (van der Linden, 2007) with rapid-guessing flags. |
| Authors: | Okan Bulut [aut, cre] |
| Maintainer: | Okan Bulut <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.1.0 |
| Built: | 2026-10-29 22:04:16 UTC |
| Source: | https://github.com/okanbulut/mirtverse |
Add person scores to the response data
## S3 method for class 'SingleGroupClass' augment(x, data = NULL, method = "EAP", person_fit = FALSE, ...)## S3 method for class 'SingleGroupClass' augment(x, data = NULL, method = "EAP", person_fit = FALSE, ...)
x |
a model returned by |
data |
optional data frame to bind the scores to. Defaults to the response data used to fit the model. |
method |
scoring method passed to |
person_fit |
logical; add the standardized log-likelihood person-fit
statistic |
... |
further arguments passed to |
A tibble with the data plus .F1 (one column per factor), .se_F1,
and optionally .Zh.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) head(augment(mod))mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) head(augment(mod))
A single entry point to the mirtverse graphics.
## S3 method for class 'SingleGroupClass' autoplot( object, type = c("trace", "expected", "info", "iteminfo", "se", "wright", "itemfit", "q3", "scores"), ... )## S3 method for class 'SingleGroupClass' autoplot( object, type = c("trace", "expected", "info", "iteminfo", "se", "wright", "itemfit", "q3", "scores"), ... )
object |
a model returned by |
type |
one of |
... |
passed to the matching |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) ggplot2::autoplot(mod, "wright")mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) ggplot2::autoplot(mod, "wright")
Tests every item for DIF between groups (for example by gender or language)
and reports the results as a tidy table with effect sizes. The analysis uses
the constrained-baseline approach: a multiple-group model is fitted with all
item parameters equal across groups and free latent means and variances,
then each item's parameters are freed in turn and compared with a
likelihood-ratio test (mirt::DIF() with scheme = "drop").
dif( x, group = NULL, model = "2PL", items = NULL, which.par = NULL, p_adjust = "BH", alpha = 0.05, verbose = FALSE, ... )dif( x, group = NULL, model = "2PL", items = NULL, which.par = NULL, p_adjust = "BH", alpha = 0.05, verbose = FALSE, ... )
x |
a data frame or matrix of item responses, or a
|
group |
the grouping variable: a vector with one value per respondent,
or the name of a column of |
model |
item type passed to |
items |
items to test, by name or position. Defaults to all items; untested items act as anchors. |
which.par |
parameters to test. Defaults to all estimated item
parameters (for example |
p_adjust |
p-value adjustment across items (see |
alpha |
significance level for flagging an item, applied to the adjusted p-values. |
verbose |
logical; show progress. |
... |
further arguments passed to |
Effect sizes are reported for two-group comparisons as the difference in
expected item score between the focal and the reference group at the same
ability, averaged over the focal group's ability distribution: esd is the
signed difference (positive values mean the item is easier for, or favours,
the focal group) and uesd the unsigned difference, which also captures
crossing (non-uniform) DIF. Both are on the item score scale, so for 0/1
items they are differences in the probability of a correct answer.
An object of class mv_dif with elements table (one row per
tested item: item, X2, df, p.value, p.adjusted, flag, esd,
uesd, converged), baseline (the constrained model), models (the
models with each item freed), groups, reference, focal,
which.par, alpha and p_adjust. Use tidy(), gg_dif() and
interpret() on it.
set.seed(1) a <- matrix(rlnorm(8, 0.2, 0.3)); d <- matrix(rnorm(8)) d2 <- d; d2[1] <- d2[1] - 1 data <- rbind(simdata(a, d, 400, itemtype = "2PL"), simdata(a, d2, 400, itemtype = "2PL")) gender <- rep(c("F", "M"), each = 400) res <- dif(data, group = gender) res gg_dif(res) interpret(res)set.seed(1) a <- matrix(rlnorm(8, 0.2, 0.3)); d <- matrix(rnorm(8)) d2 <- d; d2[1] <- d2[1] - 1 data <- rbind(simdata(a, d, 400, itemtype = "2PL"), simdata(a, d2, 400, itemtype = "2PL")) gender <- rep(c("F", "M"), each = 400) res <- dif(data, group = gender) res gg_dif(res) interpret(res)
Fits van der Linden's (2007) hierarchical framework on top of a fitted mirt model. Response times follow a lognormal model,
where is the time intensity of item j, its time
discrimination and the speed of person i. Ability and speed
are bivariate normal with correlation .
fit_rt( x, rt, flag_method = c("residual", "nt10"), z_crit = 1.96, quadpts = c(41, 21), tol = 1e-04, maxit = 500, verbose = FALSE )fit_rt( x, rt, flag_method = c("residual", "nt10"), z_crit = 1.96, quadpts = c(41, 21), tol = 1e-04, maxit = 500, verbose = FALSE )
x |
a unidimensional model from |
rt |
a matrix or data frame of response times (in seconds, or any positive unit) with the same rows and columns as the response data. Missing values are allowed. |
flag_method |
|
z_crit |
critical value for the residual method. |
quadpts |
number of quadrature points per dimension. |
tol |
convergence tolerance (largest parameter change). |
maxit |
maximum number of EM iterations. |
verbose |
logical; print the log-likelihood during estimation. |
The item response parameters are taken from x and held fixed; the
response-time parameters, the speed variance and the ability-speed
correlation are estimated by marginal maximum likelihood with an EM
algorithm on a two-dimensional quadrature grid. Persons are then scored
jointly, so response times act as collateral information for ability.
Standard errors come from the cross-product of the individual score
contributions.
Rapid responses are flagged in two ways: "residual" marks responses that
are much faster than expected for that person on that item (standardized
log-time residual below -z_crit); "nt10" uses the normative threshold of
10% of the item's mean time (Wise & Ma, 2012). Response time effort (RTE;
Wise & Kong, 2005) is the proportion of a person's responses that are not
flagged. The person-fit statistic (van der Linden & Guo, 2008)
flags aberrant overall timing.
An object of class mv_rt with elements items (time intensity
and discrimination with SEs), population (speed SD and ability-speed
correlation), persons (joint ability and speed estimates, RTE and
), flags (logical matrix of rapid responses), logLik,
iterations and converged. Use tidy(), glance(), augment(),
autoplot() and interpret() on it.
van der Linden, W. J. (2007). A hierarchical framework for modeling speed and accuracy on test items. Psychometrika, 72, 287-308.
van der Linden, W. J., & Guo, F. (2008). Bayesian procedures for identifying aberrant response-time patterns in adaptive testing. Psychometrika, 73, 365-384.
Wise, S. L., & Kong, X. (2005). Response time effort: A new measure of examinee motivation in computer-based tests. Applied Measurement in Education, 18, 163-183.
Wise, S. L., & Ma, L. (2012). Setting response time thresholds for a CAT item pool: The normative threshold method. Paper presented at NCME.
sim <- sim_rt(N = 1000, J = 15, rho = -0.4, seed = 1) mod <- mirt(sim$responses, 1, verbose = FALSE) fit <- fit_rt(mod, sim$rt) fit tidy(fit)sim <- sim_rt(N = 1000, J = 15, rho = -0.4, seed = 1) mod <- mirt(sim$responses, 1, verbose = FALSE) fit <- fit_rt(mod, sim$rt) fit tidy(fit)
type = "effect" shows the signed expected-score difference for each item,
with flagged items highlighted; type = "curves" overlays the expected item
score curves of each group for the chosen (by default the flagged) items.
gg_dif( x, type = c("effect", "curves"), which.items = NULL, theta_lim = c(-4, 4) )gg_dif( x, type = c("effect", "curves"), which.items = NULL, theta_lim = c(-4, 4) )
x |
an |
type |
|
which.items |
items to draw for |
theta_lim |
range of the latent trait for |
A ggplot object.
set.seed(1) a <- matrix(rlnorm(8, 0.2, 0.3)); d <- matrix(rnorm(8)) d2 <- d; d2[1] <- d2[1] - 1 data <- rbind(simdata(a, d, 400, itemtype = "2PL"), simdata(a, d2, 400, itemtype = "2PL")) res <- dif(data, group = rep(c("F", "M"), each = 400)) gg_dif(res) gg_dif(res, type = "curves")set.seed(1) a <- matrix(rlnorm(8, 0.2, 0.3)); d <- matrix(rnorm(8)) d2 <- d; d2[1] <- d2[1] - 1 data <- rbind(simdata(a, d, 400, itemtype = "2PL"), simdata(a, d2, 400, itemtype = "2PL")) res <- dif(data, group = rep(c("F", "M"), each = 400)) gg_dif(res) gg_dif(res, type = "curves")
Groups examinees by their ability estimate and compares the observed mean item score in each group (with 95% intervals) with the model-implied curve. Large departures point to misfit.
gg_empirical(x, item, bins = 10, theta_lim = c(-3, 3))gg_empirical(x, item, bins = 10, theta_lim = c(-3, 3))
x |
a unidimensional model returned by |
item |
a single item, by position or name. |
bins |
number of ability groups. |
theta_lim |
range of the latent trait. |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_empirical(mod, 1)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_empirical(mod, 1)
Test and item information curves
gg_info( x, type = c("test", "items", "se"), which.items = NULL, theta_lim = c(-4, 4) )gg_info( x, type = c("test", "items", "se"), which.items = NULL, theta_lim = c(-4, 4) )
x |
a unidimensional model returned by |
type |
|
which.items |
items to include for |
theta_lim |
range of the latent trait. |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_info(mod) gg_info(mod, type = "items")mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_info(mod) gg_info(mod, type = "items")
Shows the RMSEA of the S-X2 item-fit statistic for each item and marks
items whose p-value falls below alpha.
gg_itemfit(x, alpha = 0.01, p_adjust = "none")gg_itemfit(x, alpha = 0.01, p_adjust = "none")
x |
a model returned by |
alpha |
significance level for flagging misfit. |
p_adjust |
p-value adjustment (see |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_itemfit(mod)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_itemfit(mod)
Local dependence heatmap (Yen's Q3)
gg_q3(x, cutoff = 0.2, label = TRUE)gg_q3(x, cutoff = 0.2, label = TRUE)
x |
a model returned by |
cutoff |
absolute residual correlation above the average Q3 that is marked as possible local dependence (0.2 by default, Christensen et al., 2017). |
label |
logical; print values in flagged cells. |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_q3(mod)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_q3(mod)
Distribution of person scores
gg_scores(x, method = "EAP")gg_scores(x, method = "EAP")
x |
a model returned by |
method |
scoring method passed to |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_scores(mod)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_scores(mod)
Item characteristic (trace) curves
gg_trace( x, which.items = NULL, type = c("prob", "expected"), facet = TRUE, theta_lim = c(-4, 4) )gg_trace( x, which.items = NULL, type = c("prob", "expected"), facet = TRUE, theta_lim = c(-4, 4) )
x |
a unidimensional model returned by |
which.items |
items to plot, by position or name. Defaults to all. |
type |
|
facet |
logical; one panel per item. If |
theta_lim |
range of the latent trait. |
A ggplot object.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_trace(mod) gg_trace(mod, facet = FALSE)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) gg_trace(mod) gg_trace(mod, facet = FALSE)
Places the distribution of person estimates beside the item locations on the same latent scale, so you can see whether the test is targeted at the examinees. Polytomous items show each threshold.
gg_wright(x, method = "EAP", thresholds = TRUE, bins = 30)gg_wright(x, method = "EAP", thresholds = TRUE, bins = 30)
x |
a unidimensional model returned by |
method |
scoring method for persons, passed to |
thresholds |
logical; plot every threshold of polytomous items rather than their average location. |
bins |
number of histogram bins for persons. |
A patchwork object (a combined ggplot).
mod <- mirt(Science, 1, verbose = FALSE) gg_wright(mod)mod <- mirt(Science, 1, verbose = FALSE) gg_wright(mod)
Collects sample size, information criteria, convergence, limited-information
fit (M2 or C2) and marginal reliability in a single row, which makes it easy
to compare models with rbind().
## S3 method for class 'SingleGroupClass' glance(x, fit = TRUE, ...) ## S3 method for class 'MultipleGroupClass' glance(x, ...)## S3 method for class 'SingleGroupClass' glance(x, fit = TRUE, ...) ## S3 method for class 'MultipleGroupClass' glance(x, ...)
x |
a model returned by |
fit |
logical; compute the M2-family fit statistics. For polytomous items the C2 statistic is used. |
... |
unused. |
A one-row tibble.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) glance(mod)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) glance(mod)
Packs the key results of a model (parameters, fit, reliability and the rule-based interpretation) into a text prompt you can paste into any large language model to get a longer narrative or a draft technical-report section. Nothing is sent anywhere by this function.
interpret_prompt(x, audience = "a psychometric technical report")interpret_prompt(x, audience = "a psychometric technical report")
x |
a model from |
audience |
who the text is for, e.g. |
A single character string.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) cat(interpret_prompt(mod))mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) cat(interpret_prompt(mod))
Turns a fitted model into short, readable statements about model fit, reliability, test targeting, problem items, local dependence and person fit. Each statement quotes the numbers it rests on, so the text can go straight into a report. The rules used are documented in the Details.
## S3 method for class 'mv_dif' interpret(x, ...) interpret(x, ...) ## S3 method for class 'SingleGroupClass' interpret(x, alpha = 0.01, ...) ## S3 method for class 'mv_model_selection' interpret(x, ...) ## S3 method for class 'mv_rt' interpret(x, ...)## S3 method for class 'mv_dif' interpret(x, ...) interpret(x, ...) ## S3 method for class 'SingleGroupClass' interpret(x, alpha = 0.01, ...) ## S3 method for class 'mv_model_selection' interpret(x, ...) ## S3 method for class 'mv_rt' interpret(x, ...)
x |
a model from |
... |
unused. |
alpha |
significance level for item misfit. |
Rules of thumb used:
RMSEA (M2/C2): <= .05 close, <= .08 reasonable, <= .10 mediocre, otherwise poor.
Marginal reliability: >= .90 excellent, >= .80 good, >= .70 acceptable.
Discrimination: < 0.5 low, > 4 suspiciously high; location beyond +/- 3
extreme; guessing > .30 high; S-X2 p < alpha misfit.
Local dependence: Q3 more than 0.2 above the average Q3.
Person fit: Zh < -1.96 flags aberrant response patterns.
An object of class mv_interpretation: a named list of character
vectors, one per section. It prints as formatted text; use
as.character() or format(x, "markdown") to reuse it.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) interpret(mod)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) interpret(mod)
A one-page visual summary of a single item for item review meetings: trace curves, information, observed versus expected scores, the response distribution and a key-statistics panel with a traffic-light status.
item_card(x, item, alpha = 0.01, tab = NULL)item_card(x, item, alpha = 0.01, tab = NULL)
x |
a unidimensional model from |
item |
a single item, by position or name. |
alpha |
significance level for item misfit. |
tab |
optional precomputed |
Status rules: red for misfit, low discrimination (a < 0.5) or an
item-total correlation below .10; amber for any other flag (see
item_table()); green otherwise.
A patchwork object.
mod <- mirt(Science, 1, verbose = FALSE) item_card(mod, "Work")mod <- mirt(Science, 1, verbose = FALSE) item_card(mod, "Work")
Health cards for many items
item_cards(x, which.items = NULL, file = NULL, alpha = 0.01)item_cards(x, which.items = NULL, file = NULL, alpha = 0.01)
x |
a unidimensional model from |
which.items |
items to include (default: all). |
file |
optional path to an |
alpha |
significance level for item misfit. |
A named list of cards (invisibly when file is given).
mod <- mirt(Science, 1, verbose = FALSE) cards <- item_cards(mod) item_cards(mod, file = tempfile(fileext = ".html"))mod <- mirt(Science, 1, verbose = FALSE) cards <- item_cards(mod) item_cards(mod, file = tempfile(fileext = ".html"))
Combines classical item statistics (mirt::itemstats()), IRT parameters and
item fit (mirt::itemfit()) into one row per item, with a flag column
that marks items worth reviewing.
item_table(x, fit_stats = "S_X2", p_adjust = "none", alpha = 0.01)item_table(x, fit_stats = "S_X2", p_adjust = "none", alpha = 0.01)
x |
a model returned by |
fit_stats |
fit statistic passed to |
p_adjust |
p-value adjustment method (see |
alpha |
significance level used for misfit flags. |
A tibble with one row per item.
mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) item_table(mod)mod <- mirt(expand.table(LSAT7), 1, verbose = FALSE) item_table(mod)
Opens a point-and-click application for a complete IRT analysis: load and score data, explore items, let mirtverse pick a model or choose one yourself, read the plain-language interpretation, inspect item health cards and graphics, score examinees, analyse response times, and download an HTML report. Every step is written into an R script you can download, so the analysis is reproducible and a good way to learn the R code.
launch_workbench(data = NULL, ...) workbench_app(data = NULL)launch_workbench(data = NULL, ...) workbench_app(data = NULL)
data |
optional data frame of item responses to start with. |
... |
passed to |
Runs the app; returns nothing useful.
if (interactive()) { launch_workbench() launch_workbench(expand.table(LSAT7)) }if (interactive()) { launch_workbench() launch_workbench(expand.table(LSAT7)) }
Describe the analysis in your own words, for example "fit a 2PL, check DIF
by gender and make a report", and mv_ask() writes a complete, commented R
script for it. The request is turned into an analysis plan (see
mv_plan()), checked against your data, and the script is built from
tested templates, so it only uses mirt and mirtverse functions with checked
arguments. Nothing is run until you call run_script().
mv_ask( request = NULL, data = NULL, plan = NULL, provider = NULL, model = NULL, anonymize = FALSE, dry_run = FALSE, ask = interactive(), ... )mv_ask( request = NULL, data = NULL, plan = NULL, provider = NULL, model = NULL, anonymize = FALSE, dry_run = FALSE, ask = interactive(), ... )
request |
a plain-language description of the analysis. To change an
earlier script, pass it first: |
data |
the data: a data frame, or the path of a |
plan |
an |
provider |
|
model |
the AI model name; see |
anonymize |
logical; replace column names with V1, V2, ... (and drop category labels) before anything is sent to the AI model. The names are restored locally. |
dry_run |
logical; print exactly what would be sent to the AI model and return it, without sending anything or writing a script. |
ask |
logical; ask follow-up questions in the console when the keyword
parser needs more information. If |
... |
unused; there to catch a mistyped argument such as |
Requests are understood by an AI model set up with mv_ask_setup()
(Claude, OpenAI GPT or a local Ollama model), or, when none is set up, by a
built-in keyword parser that works offline and asks follow-up questions in
the console when something is unclear. The AI model only sees your request
and a summary of the columns (profile_data()); never individual
responses. Use dry_run = TRUE to see exactly what would be sent.
An object of class mv_script with elements script (the code as
a character vector), plan, profile (see profile_data()),
request, data_name and parser (what understood the request).
Printing it shows the plan, any assumptions and the code. With
dry_run = TRUE, the text that would be sent, invisibly.
run_script(), save_script(), mv_plan(), mv_ask_setup().
scr <- mv_ask("fit a graded response model, plot the curves and summarise", data = Science, provider = "none") scr scr <- mv_ask(scr, "also make a report") mv_ask("check DIF by gender", data = Science, dry_run = TRUE) res <- run_script(scr, echo = FALSE) res$modscr <- mv_ask("fit a graded response model, plot the curves and summarise", data = Science, provider = "none") scr scr <- mv_ask(scr, "also make a report") mv_ask("check DIF by gender", data = Science, dry_run = TRUE) res <- run_script(scr, echo = FALSE) res$mod
Chooses which AI model mv_ask() uses to understand plain-language
requests and stores the API key so you only do this once. Three providers
are supported through the ellmer package:
mv_ask_setup( provider = c("claude", "openai", "ollama", "none"), model = NULL, key = NULL, save = c("ask", "renviron", "keyring", "none"), test = TRUE )mv_ask_setup( provider = c("claude", "openai", "ollama", "none"), model = NULL, key = NULL, save = c("ask", "renviron", "keyring", "none"), test = TRUE )
provider |
|
model |
model name; defaults to |
key |
the API key. If |
save |
where to keep the key and settings for future sessions:
|
test |
logical; send one tiny test request to check the setup. |
"claude": Anthropic's Claude, with your own key from
https://console.anthropic.com (stored as ANTHROPIC_API_KEY).
"openai": OpenAI's GPT models, with your own key from
https://platform.openai.com (stored as OPENAI_API_KEY).
"ollama": a free model running on your own computer with Ollama
(https://ollama.com). Install Ollama, run ollama pull qwen2.5 (or
another model) once, and nothing ever leaves your machine.
Use provider = "none" to always use the built-in keyword parser, which
needs no AI model and no internet connection.
Only a summary of your columns (see profile_data()) and your request are
sent; never individual responses. Keys are never written into scripts,
reports or mv_script objects.
The provider and model, invisibly.
## Not run: mv_ask_setup("claude") mv_ask_setup("ollama", model = "qwen2.5") ## End(Not run)## Not run: mv_ask_setup("claude") mv_ask_setup("ollama", model = "qwen2.5") ## End(Not run)
A plan lists, in a structured form, what the generated script should do:
which columns are items, which model to fit, which group to test for DIF
and which outputs to produce. mv_ask() fills a plan from a plain-language
request, but a plan can also be written by hand and passed to
mv_ask(plan = ), or changed with update_plan().
mv_plan( items = NULL, model = "auto", nfact = 1, group = NULL, missing = NULL, key = NULL, rt = NULL, steps = c("describe", "fitcheck", "interpret"), options = list(), assumptions = character() ) update_plan(plan, ...)mv_plan( items = NULL, model = "auto", nfact = 1, group = NULL, missing = NULL, key = NULL, rt = NULL, steps = c("describe", "fitcheck", "interpret"), options = list(), assumptions = character() ) update_plan(plan, ...)
items |
item columns: a character vector of names, a range such as
|
model |
|
nfact |
number of latent dimensions (1 to 3). |
group |
name of a grouping column (e.g. |
missing |
numeric codes that mean "missing", e.g. |
key |
answer key for multiple-choice items that are not yet scored. |
rt |
response-time columns, one per item and in the same order.
Setting it adds the |
steps |
the analysis steps, any of |
options |
per-step options as a named list of lists, e.g.
|
assumptions |
notes about how the request was understood; they are printed with the plan and written as comments in the script. |
plan |
an |
... |
fields to change, as in |
An object of class mv_plan.
mv_plan(model = "2PL", group = "gender", steps = c("fitcheck", "report"))mv_plan(model = "2PL", group = "gender", steps = c("fitcheck", "report"))
Writes a self-contained HTML report (no internet connection or extra software needed to open it) covering the plain-language summary, model fit, item statistics and parameters, graphics, a sum-score conversion table, optional item health cards and the R code needed to reproduce the analysis.
mv_report( x, file = "mirtverse-report.html", title = "IRT analysis report", author = NULL, cards = NULL, alpha = 0.01, dif = NULL, code = NULL, open = interactive() && !isTRUE(getOption("mirtverse.dry_run")) )mv_report( x, file = "mirtverse-report.html", title = "IRT analysis report", author = NULL, cards = NULL, alpha = 0.01, dif = NULL, code = NULL, open = interactive() && !isTRUE(getOption("mirtverse.dry_run")) )
x |
a unidimensional model from |
file |
path of the |
title |
report title. |
author |
optional author line. |
cards |
logical; include an item health card for every item. Defaults
to |
alpha |
significance level for item misfit. |
dif |
optional |
code |
optional character vector of R code to show in the reproducibility section (the workbench fills this in automatically). |
open |
logical; open the report in a browser afterwards. |
The path to the report, invisibly.
mod <- mirt(Science, 1, verbose = FALSE) f <- mv_report(mod, file = tempfile(fileext = ".html"))mod <- mirt(Science, 1, verbose = FALSE) f <- mv_report(mod, file = tempfile(fileext = ".html"))
Describes each column of a data set (type, number of distinct values,
range, share missing) and guesses its role: an item (whole numbers with
few categories), a group variable (few categories, e.g. gender), an id,
a response time (rt), or other. This summary is the only information
mv_ask() ever shares with an AI model; individual responses are never
included. Category labels are kept only for likely grouping variables.
profile_data(data)profile_data(data)
data |
a data frame. |
A tibble of class mv_profile with one row per column: column,
type, n_distinct, min, max, prop_missing, role and levels.
The number of rows of data is stored in the n attribute.
profile_data(Science)profile_data(Science)
run_script() runs the script in a fresh environment and returns the
objects it created (for example mod, sel, dif_res, scores).
With check = TRUE it first runs the whole script on simulated data with
the same structure as yours (same items, categories and groups) in a
temporary folder, so errors show up before your data are touched.
save_script() writes the script to a .R file.
run_script(x, check = FALSE, echo = interactive()) save_script(x, file = "analysis.R", open = FALSE)run_script(x, check = FALSE, echo = interactive()) save_script(x, file = "analysis.R", open = FALSE)
x |
an |
check |
logical; do a dry run on simulated data first. |
echo |
logical; print each line and its output as it runs. |
file |
path of the |
open |
logical; open the file in the RStudio or Positron editor (needs the rstudioapi package). |
run_script(): a named list of the objects the script created,
invisibly. save_script(): the file path, invisibly.
scr <- mv_ask(data = Science, plan = mv_plan(model = "graded", steps = "fitcheck")) f <- save_script(scr, tempfile(fileext = ".R")) res <- run_script(scr, echo = FALSE)scr <- mv_ask(data = Science, plan = mv_plan(model = "graded", steps = "fitcheck")) f <- save_script(scr, tempfile(fileext = ".R")) res <- run_script(scr, echo = FALSE)
Fits a set of candidate IRT models to the same data, compares them on information criteria, likelihood-ratio tests and limited-information fit, and recommends one with a plain-language explanation.
select_model( data, candidates = NULL, dims = 1, criterion = c("BIC", "AIC", "SABIC"), fit = TRUE, verbose = TRUE, ... )select_model( data, candidates = NULL, dims = 1, criterion = c("BIC", "AIC", "SABIC"), fit = TRUE, verbose = TRUE, ... )
data |
a data frame or matrix of item responses. |
candidates |
optional character vector of |
dims |
number(s) of latent dimensions to try. |
criterion |
information criterion used to rank models. |
fit |
logical; compute M2/C2 fit statistics for each model. |
verbose |
logical; print progress. |
... |
further arguments passed to |
By default the candidates depend on the data: for dichotomous items the
Rasch, 2PL and 3PL models; for polytomous (or mixed) items the partial
credit (Rasch), generalized partial credit and graded response models.
Set dims = 1:2 to also try two-factor exploratory versions.
An object of class mv_model_selection with elements table
(comparison table), models (fitted models), best (the recommended
model), lrt (likelihood-ratio tests between nested models) and
explanation (text).
sel <- select_model(expand.table(LSAT7)) sel sel$bestsel <- select_model(expand.table(LSAT7)) sel sel$best
Generates data from a 2PL model for responses and the lognormal model for
response times, with correlated ability and speed. Useful for teaching and
for checking fit_rt().
sim_rt(N = 1000, J = 20, rho = -0.3, sd_speed = 0.3, rapid = 0, seed = NULL)sim_rt(N = 1000, J = 20, rho = -0.3, sd_speed = 0.3, rapid = 0, seed = NULL)
N |
number of persons. |
J |
number of items. |
rho |
correlation between ability and speed. |
sd_speed |
standard deviation of speed. |
rapid |
proportion of persons who rapid-guess on a random 30% of the items (fast responses, correct at chance level .25). |
seed |
optional random seed. |
A list with responses, rt (seconds), theta, tau, rapid
(logical matrix of simulated rapid guesses) and the true item parameters
a, d, beta, alpha.
sim <- sim_rt(N = 200, J = 10, seed = 1) str(sim, max.level = 1)sim <- sim_rt(N = 200, J = 10, seed = 1) str(sim, max.level = 1)
A clean ggplot2 theme for psychometric graphics
theme_mirtverse(base_size = 11)theme_mirtverse(base_size = 11)
base_size |
base font size. |
A ggplot2 theme.
Returns one row per estimated parameter, ready for dplyr, tables, and
plotting. For unidimensional models the traditional IRT parameterization
(discrimination a, difficulty b, guessing g, upper bound u) is used
by default; multidimensional models are reported in slope-intercept form.
## S3 method for class 'SingleGroupClass' tidy( x, IRTpars = TRUE, conf.int = FALSE, conf.level = 0.95, group_pars = FALSE, ... ) ## S3 method for class 'MultipleGroupClass' tidy( x, IRTpars = TRUE, conf.int = FALSE, conf.level = 0.95, group_pars = TRUE, ... )## S3 method for class 'SingleGroupClass' tidy( x, IRTpars = TRUE, conf.int = FALSE, conf.level = 0.95, group_pars = FALSE, ... ) ## S3 method for class 'MultipleGroupClass' tidy( x, IRTpars = TRUE, conf.int = FALSE, conf.level = 0.95, group_pars = TRUE, ... )
x |
a model returned by |
IRTpars |
logical; use the traditional IRT parameterization when
possible. Ignored (treated as |
conf.int |
logical; add Wald confidence limits (needs standard errors,
i.e. the model fitted with |
conf.level |
confidence level for |
group_pars |
logical; also return latent mean and (co)variance parameters. |
... |
unused. |
A tibble with columns item, itemtype, term, estimate, and
std.error (plus group, conf.low, conf.high when relevant).
mod <- mirt(expand.table(LSAT7), 1, SE = TRUE, verbose = FALSE) tidy(mod) tidy(mod, conf.int = TRUE)mod <- mirt(expand.table(LSAT7), 1, SE = TRUE, verbose = FALSE) tidy(mod) tidy(mod, conf.int = TRUE)