Skip to main content

Multidimensional Item Response Theory for Python

Project description

mirt

Multidimensional Item Response Theory for Python

A comprehensive Python implementation of Item Response Theory (IRT) models with a high-performance Rust backend, inspired by R's mirt package.

Features

Core IRT Models

  • Dichotomous: 1PL (Rasch), 2PL, 3PL, 4PL
  • Polytomous: GRM, GPCM, PCM, NRM
  • Multidimensional: Exploratory and confirmatory MIRT
  • Bifactor: Bifactor and hierarchical models

Advanced Models

  • Cognitive Diagnostic: DINA, DINO, G-DINA
  • Testlet: Random effects for item bundles
  • Mixture IRT: Latent class IRT models
  • Zero-Inflated: ZI-2PL, ZI-3PL, Hurdle IRT
  • Unfolding: GGUM, Ideal Point, Hyperbolic Cosine
  • Nonparametric: Monotonic spline IRFs

Estimation Methods

  • EM Algorithm: Gauss-Hermite quadrature (with Rust acceleration)
  • MHRM: Metropolis-Hastings Robbins-Monro
  • MCMC: Gibbs sampling for Bayesian estimation
  • MCEM/QMCEM: Monte Carlo EM for high dimensions

Computerized Adaptive Testing (CAT)

  • Item selection: MFI, MEI, KL divergence, a-stratified, Urry
  • Stopping rules: SE threshold, max items, classification
  • Exposure control: Sympson-Hetter, randomesque, progressive
  • Content balancing: Blueprint constraints

Diagnostics & DIF

  • Item fit: Infit, outfit, S-X2
  • Person fit: Zh, lz, infit/outfit
  • Model fit: M2, RMSEA, CFI, TLI, SRMSR
  • DIF analysis: Likelihood ratio, Wald, Lord, Raju
  • DTF/DRF: Differential test/response functioning
  • SIBTEST: Simultaneous item bias test
  • Local dependence: Q3, chi-square residuals

Additional Features

  • Multiple group analysis with invariance testing
  • Bootstrap standard errors and confidence intervals
  • Plausible values for population inference
  • Missing data imputation
  • Built-in sample datasets
  • Plotting (ICC, information, Wright maps, DIF)
  • DataFrame output (pandas or polars)

Installation

pip install mirt

With optional dependencies:

pip install mirt[pandas]    # DataFrame support via pandas
pip install mirt[polars]    # DataFrame support via polars
pip install mirt[dev]       # Development tools

For plotting support:

pip install matplotlib

Quick Start

import mirt

# Load a sample dataset
dataset = mirt.load_dataset("LSAT7")
responses = dataset["data"]

# Fit a 2PL model
result = mirt.fit_mirt(responses, model="2PL")
print(result.summary())

# Score respondents
scores = mirt.fscores(result, responses, method="EAP")
print(scores.to_dataframe().head())

Examples

Simulating Data

import mirt
import numpy as np

# Basic simulation
responses = mirt.simdata(model="2PL", n_persons=500, n_items=20, seed=42)

# With specific parameters
a = np.random.lognormal(0, 0.3, size=20)
b = np.random.normal(0, 1, size=20)
responses = mirt.simdata(model="2PL", discrimination=a, difficulty=b, n_persons=1000)

# Polytomous data
likert_data = mirt.simdata(model="GRM", n_categories=5, n_persons=500, n_items=15)

Fitting Models

# Dichotomous models
result_1pl = mirt.fit_mirt(responses, model="1PL")
result_2pl = mirt.fit_mirt(responses, model="2PL")
result_3pl = mirt.fit_mirt(responses, model="3PL")

# Polytomous models
result_grm = mirt.fit_mirt(likert_data, model="GRM", n_categories=5)
result_gpcm = mirt.fit_mirt(likert_data, model="GPCM", n_categories=5)

# Multidimensional
result_mirt = mirt.fit_mirt(responses, model="2PL", n_factors=2)

Person Scoring

# Different methods
eap = mirt.fscores(result, responses, method="EAP")
map_scores = mirt.fscores(result, responses, method="MAP")
ml = mirt.fscores(result, responses, method="ML")

# Access estimates
print(eap.theta)            # Ability estimates
print(eap.standard_error)   # Standard errors

Diagnostics

# Item fit
item_fit = mirt.itemfit(result, responses)
print(item_fit)

# Person fit
person_fit = mirt.personfit(result, responses)
aberrant = person_fit[person_fit["Zh"] < -2]

# Model fit indices
fit_indices = mirt.compute_fit_indices(result.model, responses)
print(fit_indices)

# Model comparison
results = [result_1pl, result_2pl, result_3pl]
comparison = mirt.compare_models(results)

DIF Analysis

groups = np.array([0] * 250 + [1] * 250)

# Likelihood ratio test
dif_lr = mirt.dif(responses, groups, method="likelihood_ratio")

# Other methods
dif_wald = mirt.dif(responses, groups, method="wald")
dif_lord = mirt.dif(responses, groups, method="lord")
dif_raju = mirt.dif(responses, groups, method="raju")

Multiple Group Analysis

from mirt.multigroup import fit_multigroup, compare_invariance

# Fit with specific invariance level
result = fit_multigroup(responses, groups, model="2PL", invariance="metric")

# Compare all invariance levels
results = compare_invariance(responses, groups, model="2PL", verbose=True)
# Returns: {'configural': ..., 'metric': ..., 'scalar': ..., 'strict': ...}

Computerized Adaptive Testing

from mirt.cat import CATEngine

# Create CAT engine
cat = CATEngine(result.model, se_threshold=0.3, max_items=20)

# Run a simulation
sim_results = cat.run_batch_simulation(
    true_thetas=np.linspace(-2, 2, 11),
    n_replications=100,
)

# Interactive session
state = cat.get_current_state()
while not state.is_complete:
    item = state.next_item
    response = get_examinee_response(item)  # Your function
    state = cat.administer_item(response)

final = cat.get_result()
print(final.summary())

Advanced Models

# Cognitive Diagnostic Models
from mirt import fit_cdm
q_matrix = np.array([[1, 0], [1, 1], [0, 1], [1, 1]])
cdm_result = fit_cdm(responses, q_matrix, model="DINA")

# Mixture IRT
from mirt import fit_mixture_irt
mix_result = fit_mixture_irt(responses, n_classes=2, model="2PL")

# Testlet Model
from mirt import TestletModel, create_testlet_structure
testlet_struct = create_testlet_structure(n_items=20, testlet_sizes=[5, 5, 5, 5])

Plotting

from mirt import plot_icc, plot_information, plot_person_item_map

# Item characteristic curves
plot_icc(result.model, item_idx=[0, 1, 2])

# Test information function
plot_information(result.model)

# Wright map
plot_person_item_map(result.model, scores.theta)

Supported Models

Dichotomous Models

Model Description Parameters
1PL/Rasch One-parameter logistic difficulty (b)
2PL Two-parameter logistic discrimination (a), difficulty (b)
3PL Three-parameter logistic a, b, guessing (c)
4PL Four-parameter logistic a, b, c, upper asymptote (d)

Polytomous Models

Model Description Use Case
GRM Graded Response Model Ordered categories (Likert)
GPCM Generalized Partial Credit Partial credit scoring
PCM Partial Credit Model Rasch for polytomous
NRM Nominal Response Model Unordered categories

Advanced Models

Model Description
MIRT Multidimensional IRT
Bifactor General + specific factors
DINA/DINO Cognitive diagnostic
Testlet Local dependence modeling
Mixture IRT Latent class IRT
GGUM Generalized graded unfolding

API Reference

Main Functions

Function Description
fit_mirt() Fit IRT models
fscores() Person ability estimation
simdata() Simulate response data
itemfit() Item fit statistics
personfit() Person fit statistics
dif() DIF analysis
load_dataset() Load sample datasets

Diagnostic Functions

Function Description
compute_fit_indices() M2, RMSEA, CFI, TLI
compare_models() AIC/BIC comparison
anova_irt() Likelihood ratio tests
compute_dtf() Differential test functioning
compute_drf() Differential response functioning
sibtest() SIBTEST DIF detection

Utility Functions

Function Description
bootstrap_se() Bootstrap standard errors
bootstrap_ci() Bootstrap confidence intervals
generate_plausible_values() Plausible values
impute_responses() Missing data imputation
set_dataframe_backend() Choose pandas/polars

Comparison with R mirt

Feature R mirt Python mirt
Dichotomous models 1PL-4PL 1PL-4PL
Polytomous models GRM, GPCM, PCM, NRM GRM, GPCM, PCM, NRM
Multidimensional Full support Full support
Bifactor Yes Yes
Cognitive diagnostic mirtCAT separate Built-in (DINA, DINO)
Estimation EM, MHRM, MCMC EM, MHRM, MCMC
CAT mirtCAT package Built-in
DIF Yes Yes (LR, Wald, Lord, Raju)
Multiple groups Full support Full support
Rust acceleration No Yes (see below)

Rust Acceleration

When the Rust backend is available (automatically built during installation), the following operations are accelerated with parallel processing:

Category Accelerated Operations
Likelihood Log-likelihood computation for 2PL, 3PL, and multidimensional models
EM Algorithm E-step (posterior computation), M-step (Newton-Raphson optimization), full EM fitting
Scoring EAP scores, WLE scores, Lord-Wingersky recursion for sum scores
Diagnostics Q3 matrix, LD chi-square, infit/outfit statistics, standardized residuals
SIBTEST Beta statistic computation, all-items SIBTEST
CAT Item information, item selection, EAP updates, batch simulation
Simulation Response generation for 2PL/3PL, GRM, GPCM
Bootstrap Index generation, resampling, parallel bootstrap fitting
Plausible Values Posterior sampling, MCMC generation
MCMC Gibbs sampling for 2PL, MHRM estimation

All Rust functions fall back to pure Python implementations if the extension is not available. The Rust backend provides significant speedups for large datasets (1000+ persons) due to:

  • Rayon parallelization: Computation across persons or items runs in parallel
  • SIMD optimizations: Vectorized arithmetic where available
  • Memory efficiency: Reduced allocations compared to NumPy broadcasting

To check if Rust acceleration is available:

from mirt._rust_backend import RUST_AVAILABLE
print(f"Rust backend: {'enabled' if RUST_AVAILABLE else 'disabled'}")

Requirements

Core Dependencies (always required)

  • Python >= 3.11
  • numpy >= 1.24
  • scipy >= 1.9

Optional Dependencies

Package Purpose Installation
matplotlib Plotting (ICC, information curves, Wright maps, DIF) pip install matplotlib
pandas DataFrame output for results pip install mirt[pandas]
polars DataFrame output (faster, preferred when both installed) pip install mirt[polars]

When neither pandas nor polars is installed, functions that return DataFrames will raise an ImportError with installation instructions. Plotting functions similarly require matplotlib.

To set your preferred DataFrame backend explicitly:

import mirt
mirt.set_dataframe_backend("pandas")  # or "polars"

Development

# Clone and install
git clone https://github.com/Cameron-Lyons/mirt.git
cd mirt
pip install -e ".[dev]"

# Build Rust extension
maturin develop --release

# Run tests
pytest

# Type checking
mypy src/mirt

# Formatting
black src tests
ruff check src tests

API Stability (v1.0)

Starting with v1.0, this package follows semantic versioning.

Stable Public API

The following are guaranteed stable and will not have breaking changes in v1.x releases:

  • Core functions: fit_mirt(), fscores(), simdata(), itemfit(), personfit(), dif()
  • Result classes: FitResult, ScoreResult, CVResult, BatchFitResult
  • Model classes: All IRT models (TwoParameterLogistic, GradedResponseModel, etc.)
  • CAT: CATEngine, CATResult, CATState
  • Diagnostics: compare_models(), anova_irt(), compute_fit_indices(), sibtest()
  • Utilities: bootstrap_se(), bootstrap_ci(), generate_plausible_values(), cross_validate(), fit_models()
  • Data functions: load_dataset(), list_datasets(), set_dataframe_backend()

Experimental (may change in minor releases)

  • Internal _rust_backend module functions (use public wrappers instead)
  • MCMC samplers (GibbsSampler, MHRMEstimator) - API may be refined
  • Cognitive Diagnostic Models (DINA, DINO, fit_cdm()) - under active development

Versioning Policy

  • Major version (2.0, 3.0): Breaking API changes
  • Minor version (1.1, 1.2): New features, backward compatible
  • Patch version (1.0.1, 1.0.2): Bug fixes only

License

MIT License - see LICENSE

Citation

If you use this package in your research, please cite:

@software{mirt_python,
  author = {Lyons, Cameron},
  title = {mirt: Multidimensional Item Response Theory for Python},
  url = {https://github.com/Cameron-Lyons/mirt},
  version = {0.1.12}
}

References

  • Chalmers, R. P. (2012). mirt: A Multidimensional Item Response Theory Package for the R Environment. Journal of Statistical Software, 48(6), 1-29.
  • Bock, R. D., & Aitkin, M. (1981). Marginal maximum likelihood estimation of item parameters: Application of an EM algorithm. Psychometrika, 46(4), 443-459.
  • de la Torre, J. (2011). The generalized DINA model framework. Psychometrika, 76(2), 179-199.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mirt-1.0.0.tar.gz (276.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

mirt-1.0.0-cp312-cp312-win_amd64.whl (669.1 kB view details)

Uploaded CPython 3.12Windows x86-64

mirt-1.0.0-cp312-cp312-macosx_11_0_arm64.whl (698.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

mirt-1.0.0-cp312-cp312-macosx_10_12_x86_64.whl (742.3 kB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

mirt-1.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (772.7 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

mirt-1.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (730.9 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ ARM64

File details

Details for the file mirt-1.0.0.tar.gz.

File metadata

  • Download URL: mirt-1.0.0.tar.gz
  • Upload date:
  • Size: 276.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mirt-1.0.0.tar.gz
Algorithm Hash digest
SHA256 189657e2b5c34c6a3727e4ed2727b562fe8e00f520376168616abc4dc0179156
MD5 4ebcd84930a6e389e4636486303a79f5
BLAKE2b-256 473b667de12b3cf36696070f44ac048fc1077b49f42069003c0e27f133a0eaa1

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirt-1.0.0.tar.gz:

Publisher: release.yml on Cameron-Lyons/mirt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mirt-1.0.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: mirt-1.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 669.1 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mirt-1.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 f349e33c276140f1d982a1352c4ae82013da5bbaff2d759c8b39a405e4e5c932
MD5 22e89725045535cdd24ff80dd866c69c
BLAKE2b-256 88da7a47feda81e902896753dfef9871bfcd1ffd98227e50b5107aa0364571ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirt-1.0.0-cp312-cp312-win_amd64.whl:

Publisher: release.yml on Cameron-Lyons/mirt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mirt-1.0.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mirt-1.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ad095804156663b945723b1273e2122d0e66f7b40399a5b7f445ad472d76e086
MD5 6fb37e351ab092a32fa8812752b634dc
BLAKE2b-256 3a43940d0b8ef0cb5d3c4e1f384352da6ec07fe41b99d9132fc59984bdfc77a5

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirt-1.0.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on Cameron-Lyons/mirt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mirt-1.0.0-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for mirt-1.0.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9a3c149d4b9af01e98c6086ddc8d6eceac40b1b99a903ee021dc53a14e90acb7
MD5 2a9c6054b59157112b2cf4e3e4d5309a
BLAKE2b-256 2621aa7197ccb2c5eca537f180f479bf25990715250d895cf4437276c96d6059

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirt-1.0.0-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: release.yml on Cameron-Lyons/mirt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mirt-1.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for mirt-1.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a9e6fb54b40a61fbce1ab25ff82cc53f6341a61bc324c785b6cf40983917a0d1
MD5 e05ab12fc249a6498c88ac264a7ec2e2
BLAKE2b-256 d7a97102d20a6ead08f96231ca47d09ffed36a6889d91beaf58f25cf3f0c14d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirt-1.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on Cameron-Lyons/mirt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mirt-1.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for mirt-1.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b8afe712f9ff06b286b5c0e4913d6679c267734cedae6a822bae4bac38aa981f
MD5 fddf0bc9eef796cebcb4741ac41876c1
BLAKE2b-256 84fd9cd776bab578e157454fb54043c5f45a18e5e4b349a5eb32ddaa230c1bca

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirt-1.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on Cameron-Lyons/mirt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page