Skip to main content

IRT Equating for Unidimensional Mixed Format Test with Python

Project description

EqUMP

IRT Equating for Unidimensional Mixed Format Test with Python

Motivation

Item Respone Theory (IRT) test equating is a critical process for maintaining score comparability across different test forms. However, current implementations often rely on limited software or complex scripting environments. We introduce EqUMP, a Python package designed to streamline and democratize IRT equating for unidimensional mixed format test. Built upon the robust ecosystem of scientific computing in Python (Numpy, Scipy), it provides a flexible framework for various IRT equating methods (e.g., scale transformation, true score equating). The package is openly licensed, pip-installable, and includes comprehensive documentation and test suites, enabling researchers and practitioners to readily reproduce analysis pipelines. By leveraging Python’s accessibility and extensibility, EqUMP facilitates rigorous and reproducible test equating for a wider educational data analysists and psychometricians.

Core Principles

  • Academically faithful code and documentation
    EqUMP is designed for researchers and practitioners familiar with standard test equating literature. We follow textbook-style notation and structure—even at the cost of computational speed—to ensure clarity and pedagogical value.

  • Practical focus
    While many equating methods exist in the literature, some are infeasible in operational testing. EqUMP prioritizes features that reflect real-world usage and operational constraints. Users can request or contribute less common methods.

  • Symmetric linking constant support
    Symmetry property of equating function is a critical but often neglected aspect of Haebara or Stocking-Lord linking method. EqUMP handles this through carefully implemented two-sided(symmtric) or one-sided loss function.

Installation

pip install EqUMP

Compared to other related packages

  • Before we create this package, we analyze the packages below
  • As far as we know, there are no Python-based IRT Test Equating packages.
  • We found some R packages and commercial programs below. And summarize their features in the table below.
Package/Program Author Category scale-linking true-score observed-score kernel link
STUIRT Kim & Kolen, 2004 Standalone O X X X download
POLYEQUATE Kolen, 2004 Standalone X O O X download
IRTEQ Han, 2009 Standalone O O X X homepage
kequate Andersson et al., 2013 R O X O O cran
equateIRT Battauz, 2015 R O O O X cran
SNSequate Jorge Gonzalez, 2024 R O O O O download

Core API

Item Response Model

from EqUMP.base import IRF
# Dichotomous item
item_2pl = IRF(params={"a": 1.2, "b": 0.5}, model="2PL")
probs = item_2pl.prob(theta=0.0)
print(probs)
    
# Polytomous item with custom scores
item_gpcm = IRF(
    params={"a": 1.0, "b": [-0.5, 0.0, 0.5]},
    model="GPCM",
    scores=[0, 2, 5, 10]
)
expected = item_gpcm.expected_score(theta=0.0)

Scale Transformation

Mean-Mean

from EqUMP.linking import mean_mean
from EqUMP.tests.linking.helper import load_SNSequate_data
SNS_param_x, SNS_param_y = load_SNSequate_data()
SNS_param_new = SNS_param_x[["a","b","c"]].to_dict(orient="index") # SNSequate에서 y가 구 검사형, X가 신 검사형에 주의
SNS_param_old = SNS_param_y[["a","b","c"]].to_dict(orient="index")

res_python = mean_mean(
    params_new=SNS_param_new,
    params_old=SNS_param_old,
    common_new=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
    common_old=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
)

Mean-Sigma

from EqUMP.linking import mean_sigma
from EqUMP.tests.linking.helper import load_SNSequate_data
SNS_param_x, SNS_param_y = load_SNSequate_data()
SNS_param_new = SNS_param_x[["a","b","c"]].to_dict(orient="index") # SNSequate에서 y가 구 검사형, X가 신 검사형에 주의
SNS_param_old = SNS_param_y[["a","b","c"]].to_dict(orient="index")

res_python = mean_sigma(
    params_new=SNS_param_new,
    params_old=SNS_param_old,
    common_new=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
    common_old=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36]
)

Haebara

from EqUMP.linking import haebara
from EqUMP.tests.linking.helper import load_SNSequate_data
SNS_param_x, SNS_param_y = load_SNSequate_data()
SNS_param_new = SNS_param_x[["model", "a","b","c"]].to_dict(orient="index")
SNS_param_old = SNS_param_y[["model", "a","b","c"]].to_dict(orient="index")

res_python = haebara(
    items_new=SNS_param_new,
    items_old=SNS_param_old,
    common_new=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
    common_old=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
    D=1.7,
    quadrature="custom",
    nodes_new=np.linspace(-4, 4, 161),
    nodes_old=np.linspace(-4, 4, 161),
    weights_new=np.full(161, 0.05),
    weights_old=np.full(161, 0.05),
    symmetry=False,
)

Stocking-Lord

from EqUMP.linking import stocking_lord
from EqUMP.tests.linking.helper import load_SNSequate_data
SNS_param_x, SNS_param_y = load_SNSequate_data()
SNS_param_new = SNS_param_x[["model", "a", "b", "c"]].to_dict(orient="index")
SNS_param_old = SNS_param_y[["model", "a", "b", "c"]].to_dict(orient="index")

res_python = stocking_lord(
    items_new=SNS_param_new,
    items_old=SNS_param_old,
    common_new=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
    common_old=[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
    D=1.7,
    quadrature="custom",
    nodes_new=np.linspace(-4, 4, 161),
    nodes_old=np.linspace(-4, 4, 161),
    weights_new=np.full(161, 0.05),
    weights_old=np.full(161, 0.05),
    symmetry=False,
)

True Score Equating

from EqUMP.equating.TSE import tse

params_new = {
    0: {"a": 1.2, "b": -0.5},
    1: {"a": 1.0, "b": 0.0},
    2: {"a": 1.5, "b": 0.8},
    3: {"a": 0.9, "b": -1.2}
}
params_old = {
    0: {"a": 1.15, "b": -0.47},
    1: {"a": 0.95, "b": 0.05},
    2: {"a": 1.45, "b": 0.85},
    3: {"a": 0.85, "b": -1.15}
}
common_new = [0, 1, 2]
common_old = [0, 1, 2]
model_new = {0: "2PL", 1: "2PL", 2: "2PL", 3: "2PL"}
model_old = {0: "2PL", 1: "2PL", 2: "2PL", 3: "2PL"}
ts = 2.5
theta_eq, score_old = tse(ts, params_new, params_old, common_new, common_old, 
                           model_new, model_old, theta=0.0, D=1.702, anchor="internal")
# Returns: (theta_estimate, equivalent_score_on_old_form)

Observed Score Equating

# in developing

Kernel Methods

# in developing

How to contribute

EqUMP is actively being developed, and upcoming releases will include additional item response models and equating methods. We welcome contributions of any kind—if you’d like to get involved, please check out our contribution guidelines.

How to cite

  ```
  this section will be filled after publishing this package in a peer reviewed journal
  ```

Used by

following contents are not real at all. It's just our hope and vision


fictitious company
scale linking, true score equating

fictitious high school
item paramter estimation

CBTManager
emulate scale linking, ploting

💡 Want your organization featured? Open an Issue or Pull Request to be listed.

References

  • [1] Kolen, M. J., & Brennan, R. L. (2014). Test equating, scaling, and linking: Methods and practices (3rd ed.). Springer Science + Business Media. https://doi.org/10.1007/978-1-4939-0317-7.
  • [2] 김성훈. (2022). 문항반응이론 검사 동등화. 공동체.
  • [3] Andersson, B., Bränberg, K., & Wiberg, M. (2013). Performing the Kernel Method of Test Equating with the Package kequate. Journal of Statistical Software, 55(6), 1–25. https://doi.org/10.18637/jss.v055.i06
  • [4] Battauz, M. (2015). equateIRT: An R Package for IRT Test Equating. Journal of Statistical Software, 68(7), 1–22. https://doi.org/10.18637/jss.v068.i0

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

eqump-0.3.0.tar.gz (53.6 kB view details)

Uploaded Source

Built Distribution

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

eqump-0.3.0-py3-none-any.whl (73.1 kB view details)

Uploaded Python 3

File details

Details for the file eqump-0.3.0.tar.gz.

File metadata

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

File hashes

Hashes for eqump-0.3.0.tar.gz
Algorithm Hash digest
SHA256 a6ab1a39a0b7ea55d3c6570a27841f7c17d70ace3aafecb3ce55259305d3d707
MD5 480cf0e0b6a269608d7ef563cb6b61dd
BLAKE2b-256 e6a547ee983e748fb308e7f439f09380a47ecb81a946975e9f0375ac92e09686

See more details on using hashes here.

Provenance

The following attestation bundles were made for eqump-0.3.0.tar.gz:

Publisher: publish-pypi.yml on huni1023/EqUMP

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

File details

Details for the file eqump-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: eqump-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 73.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for eqump-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 84f5eed074cf5effa9f9f7417d241a4e76b5a00efea9ab0163e5476d4ff66ed5
MD5 acb7c6845afdabcfaf94621f6de98ac9
BLAKE2b-256 e57af00f78e9700a746cb160b57411fd4e4546708964a1225a53df0c1fd3f73e

See more details on using hashes here.

Provenance

The following attestation bundles were made for eqump-0.3.0-py3-none-any.whl:

Publisher: publish-pypi.yml on huni1023/EqUMP

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