Skip to contents

Introduction

The jmleIRT package provides an implementation of Joint Maximum Likelihood Estimation (JMLE) for the Rasch (1PL) model. It allows estimation of item difficulties and person abilities from dichotomous response data with bias correction and weighted likelihood estimation options.

Rasch Model Specification

For person p=1,,Pp = 1, \ldots, P and item i=1,,Ii = 1, \ldots, I, the Rasch model posits the probability of a correct response XpiX_{pi} as:

P(Xpi=1θp,βi)=exp(θpβi)1+exp(θpβi) P(X_{pi} = 1 \mid \theta_p, \beta_i) = \frac{\exp(\theta_p - \beta_i)}{1 + \exp(\theta_p - \beta_i)}

where θp\theta_p represents the ability of person pp and βi\beta_i the difficulty of item ii.

Joint Maximum Likelihood Estimation

The joint likelihood across all persons and items is

L(θ,β)=p=1Pi=1IP(Xpiθp,βi) L(\theta, \beta) = \prod_{p=1}^P \prod_{i=1}^I P(X_{pi} \mid \theta_p, \beta_i)

JMLE alternates updates for θp\theta_p and βi\beta_i until convergence, providing simultaneous estimates of person and item parameters.

Bias Correction

Finite samples and extreme scores induce bias in JMLE estimates. The package implements:

  • Epsilon bias stabilization: Adding a small ε>0\varepsilon > 0 to avoid infinite logits and improve numerical stability.
  • Analytical bias correction: Drawing on methods from psychometric literature to reduce bias in item difficulty estimates.

Using the jmleIRT Package

Key features: - Missing values by design are allowed (NA). - Optional epsilon adjustment (eps) to reduce estimation bias from extreme scores. - Centering based on either “items” or “persons” to ensure identifiability. - Post-hoc bias correction (bias_correction = TRUE/FALSE). - Optional computation of Warm’s weighted likelihood estimates (WLE) for person parameters (estimatewle = TRUE). - Fast Newton-Raphson optimization in C++.

Simulating Data

We first simulate a dataset of person responses.

N <- 100  # persons
I <- 10   # items
X <- matrix(rbinom(N * I, 1, 0.5), nrow = N)
# randomly set 10% of entries to missing
X[sample(length(X), size = 0.1 * length(X))] <- NA
head(X)
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,]    0    1    0    1    0    0    0    0    1     1
#> [2,]    1    1    1    0    1    0    1    1    0     0
#> [3,]    1    0    0    1    1    0    0    0    0     1
#> [4,]    0    0    0    1    0    1    1    1    1     1
#> [5,]   NA    0   NA    0    0    0   NA    1    0     0
#> [6,]    0    1    1    0    0    1    1    0    0     0

Basic JML Estimation

Run the JML estimation with centering on “items” (default):

fit <- jmle_estimation(
  X, max_iter = 500, conv = 1e-5,
  center = "items", bias_correction = FALSE,
  estimatewle = FALSE, verbose = FALSE
)

str(fit)
#> List of 7
#>  $ theta          : num [1:100] -0.466 0.364 -0.466 0.364 -1.86 ...
#>  $ beta           : num [1:10] 0.472 -0.494 -0.216 -0.269 0.124 ...
#>  $ iterations     : int 500
#>  $ converged      : logi FALSE
#>  $ bias_correction: logi FALSE
#>  $ center         : chr "items"
#>  $ wle_estimate   : num [1:100] NA NA NA NA NA NA NA NA NA NA ...
#>  - attr(*, "class")= chr [1:2] "jmleIRT" "list"

The output is a list with:

  • theta: person ability estimates
  • beta: item difficulty estimates
  • iterations: number of NR iterations
  • converged: convergence flag
  • bias_correction: whether applied
  • center: ‘items’ or ‘persons’
  • wle_estimate: person WLEs (if requested)

Bias Correction

Bias correction rescales item difficulty estimates.

fit_bc <- jmle_estimation(X, center = "items", bias_correction = TRUE)
summary(fit_bc$beta)
#>      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
#> -0.444924 -0.230269  0.009095  0.000000  0.234489  0.424776

Compare to the uncorrected version:

summary(fit$beta)
#>     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
#> -0.49436 -0.25585  0.01011  0.00000  0.26054  0.47197

Warm’s WLE Estimates

Warm’s weighted likelihood estimates can be obtained in addition to JML estimates.

fit_wle <- jmle_estimation(X, center = "items", estimatewle = TRUE)
head(fit_wle$wle_estimate)
#> [1] -0.3779268  0.3781344 -0.3779268  0.3781344 -1.4876481 -0.3779268

Handling Missing Data

The function handles missing responses (NA) without failure:

X_miss <- X
X_miss[1:5, 1:2] <- NA
fit_miss <- jmle_estimation(X_miss, center = "items")

length(fit_miss$theta)
#> [1] 100
length(fit_miss$beta)
#> [1] 10

Conclusion

The jmleIRT package provides a simple and efficient workflow for Rasch JML estimation with useful options such as centering, bias correction, and WLEs, while being robust to missing data.