Learn R Programming

tirt (version 0.1.3)

fixed_item: Fixed Item Calibration

Description

Estimates unknown item parameters using Marginal Maximum Likelihood via Expectation-Maximization Algorithm. Uses a custom Bounded Newton-Raphson solver. Supports mixed-format data containing dichotomous and polytomous responses

Usage

fixed_item(response_df, item_params_df, control = list())

Value

A list containing:

  • item_params: Estimated parameters for unknown items.

  • person_params: Estimated person parameters.

  • model_fit: A data frame containing number off estimated parameters and fit statistics such as Akaike’s Information Criterion (AIC), the Bayesian Information Criterion (BIC), and Log-Likelihood.

Arguments

response_df

A data.frame of responses. Rows=Students, Cols=Items. Data MUST be from 0-indexed (0, 1, 2...).

item_params_df

A data.frame of known parameters. Required: "item", "model".

control

A list of control parameters for the estimation algorithm:

  • max_iter: Maximum number of EM iterations (default = 50).

  • conv_crit: Convergence criterion for parameter change (default = 0.005).

  • verbose: Logical; if TRUE, prints progress to console.

Examples

Run this code
# 1. TOY EXAMPLE
# ===========================================================================
set.seed(123)
# Create a very small dataset (N=50, J=4)
N_toy <- 50
df_toy <- data.frame(
  I1 = rbinom(N_toy, 1, 0.5), I2 = rbinom(N_toy, 1, 0.6), # Known items
  U1 = rbinom(N_toy, 1, 0.5), U2 = rbinom(N_toy, 1, 0.4)  # Unknown items
)

# Define the "Known" parameters for I1 and I2
known_params <- data.frame(
  item = c("I1", "I2"),
  model = c("2PL", "2PL"),
  a = c(1.0, 1.2),
  b = c(-0.5, 0.5)
)

# Run Fixed Item Calibration with very low iterations
fit_toy <- fixed_item(df_toy, known_params, control=list(max_iter=2, verbose=FALSE))
print(head(fit_toy$item_params))
  # \donttest{
  # --- Example 2: Simulation ---
  set.seed(123)
  N <- 500
  true_theta <- rnorm(N, 0, 1)

  # 1. Simulation Helpers
  sim_2pl <- function(theta, a, b) {
    p <- 1 / (1 + exp(-1.7 * a * (theta - b)))
    rbinom(N, 1, p)
  }
  sim_poly <- function(theta, a, steps) {
    n_cat <- length(steps) + 1
    probs <- matrix(0, length(theta), n_cat)
    for(k in 1:n_cat) {
      score <- k - 1
      if(score == 0) num <- 0
      else num <- a * (score * theta - sum(steps[1:score]))
      probs[, k] <- exp(num)
    }
    probs <- probs / rowSums(probs)
    apply(probs, 1, function(x) sample(0:(n_cat-1), 1, prob=x))
  }

  # 2. Generate Data (Mixed Known/Unknown Items)
  # Items 1-5: Known Binary (2PL)
  # Items 6-10: Unknown Binary (2PL)
  # Items 11-12: Known Poly (GPCM)
  # Items 13-15: Unknown Poly (GPCM)

  resp_mat <- matrix(NA, N, 15)
  colnames(resp_mat) <- paste0("Item_", 1:15)

  # Known Binary Parameters
  a_bin <- c(1.0, 1.2, 0.9, 1.1, 0.8)
  b_bin <- c(-1, -0.5, 0, 0.5, 1)

  for(i in 1:5) resp_mat[,i] <- sim_2pl(true_theta, a_bin[i], b_bin[i])
  for(i in 6:10) resp_mat[,i] <- sim_2pl(true_theta, runif(1,0.8,1.2), rnorm(1))

  # Known Poly Parameters
  a_poly <- c(1.0, 0.8)
  d_poly <- list(c(-1, 1), c(-0.5, 0.5))

  resp_mat[,11] <- sim_poly(true_theta, a_poly[1], d_poly[[1]])
  resp_mat[,12] <- sim_poly(true_theta, a_poly[2], d_poly[[2]])
  for(i in 13:15) resp_mat[,i] <- sim_poly(true_theta, 1.0, c(-0.5, 0.5))

  df_resp <- as.data.frame(resp_mat)

  # 3. Create 'Known Parameters' Dataframe
  # This tells the function: "Fix these, Estimate the rest"
  known_df <- data.frame(
    item = c(paste0("Item_", 1:5), "Item_11", "Item_12"),
    model = c(rep("2PL", 5), rep("GPCM", 2)),
    a = c(a_bin, a_poly),
    b = c(b_bin, NA, NA),     # Binary difficulty
    step_1 = c(rep(NA, 5), -1, -0.5), # Poly steps
    step_2 = c(rep(NA, 5),  1,  0.5),
    stringsAsFactors = FALSE
  )

  # 4. Run Estimation
  res <- fixed_item(df_resp, known_df, control=list(max_iter=20))

  # View Results
  # Notice Items 1-5 and 11-12 have Status "Fixed"
  head(res$item_params, 12)

  # --- Example 2: With Package Data ---
  data("ela1", package = "tirt")

  # Let's treat the first 5 items as "Known" with arbitrary parameters
  # just to demonstrate syntax.
  df_real <- ela1[, 1:20]

  known_real <- data.frame(
    item = paste0("Q", 1:5),
    model = "2PL",
    a = 1.0,
    b = seq(-1, 1, length.out=5)
  )

  # Ideally, column names in df_real should match 'item' column in known_real
  colnames(df_real)[1:5] <- paste0("Q", 1:5)

  real_res <- fixed_item(df_real, known_real, control=list(max_iter=10))
  head(real_res$item_params)
  # }

Run the code above in your browser using DataLab