Learn R Programming

guess

Estimate learning from paired pre-test and post-test knowledge responses while accounting for lucky guesses and explicit "don't know" responses.

Choose A Model

The package exposes separate models for separate estimands. Choose the model before interpreting its output.

FunctionEstimandMain assumption
item_lca_fit()Proportion who learned each itemEach item has its own latent transition distribution
person_item_lca_fit()Shared person-level trajectory and posterior probability of learningA person has one gg, gk, or kk trajectory across all items
lca_difficulty()Item-wise LCA with guessing expressed through a difficulty linkThis is a reparameterized LCA, not an IRT model
stnd_cor()Corrected pre, post, and gain scoresThe guessing probability is supplied by the user
group_adj()Guessing-adjusted group estimatesGuessing probabilities are supplied by group and item

estimate_logit_score(), cross_sectional_learning(), and cross_sectional_learning_score() are descriptive score baselines. They do not fit Rasch or IRT models, and the bounded score is not a calibrated probability of learning.

Installation

install.packages("guess")

# Development version
devtools::install_github("finite-sample/guess")

Data Contract

Pass matching data frames with one row per person and one column per item. Pre-test and post-test columns must have the same unique names. Valid response codes are:

CodeMeaning
0 or "0"Incorrect answer
1 or "1"Correct answer
"d" or "DK"Observed "don't know" response
NAObserved "don't know" by default

Use na_as = "missing" when NA records a structural failure, such as an item that was not shown or a response lost to a technical error. Incomplete pre/post pairs are then omitted by default. Set missing_action = "error" to reject them instead.

fit <- item_lca_fit(pre_test, post_test, na_as = "missing")

fit <- item_lca_fit(
  pre_test,
  post_test,
  na_as = "missing",
  missing_action = "error"
)

Explicit "d" and "DK" values remain observed responses under either setting. Structural missingness is not treated as a latent response class.

Item-Level Learning

item_lca_fit() is the direct entry point for the model in Cor and Sood (2016). It fits every item separately from its paired response transitions.

library(guess)

item_sim <- simulate_lca(
  n = 1500,
  n_items = 4,
  gg = 0.40,
  gk = 0.30,
  kk = 0.30,
  gamma = c(0.15, 0.25, 0.35, 0.45),
  seed = 123
)

item_fit <- item_lca_fit(item_sim$pre, item_sim$post)
item_fit$learning
item_fit$params

For binary responses, the parameter rows are:

ParameterMeaning
ggGuess at both waves
gkGuess before, know after; the item-level learning estimand
kkKnow at both waves
gammaProbability of a correct response while guessing

multi_transmat() and lca_cor() expose the same workflow in two steps when you already work with transition counts.

transitions <- multi_transmat(item_sim$pre, item_sim$post)
count_fit <- lca_cor(transitions)

Person-Level Learning

person_item_lca_fit() jointly uses all repeated items. It estimates shared class proportions, item-specific guessing rates, and one posterior trajectory for each person.

person_sim <- simulate_lca(
  n = 1500,
  n_items = 5,
  gg = 0.35,
  gk = 0.35,
  kk = 0.30,
  gamma = 0.25,
  seed = 456,
  return_classes = TRUE
)

person_fit <- person_item_lca_fit(person_sim$pre, person_sim$post)
person_fit$class_priors
person_fit$gamma

posterior <- posterior_class_probs(person_fit)
p_learned <- posterior_learned(person_fit)

This model is useful only when one common trajectory across items is substantively defensible. It does not allow the same person to know one item, learn another, and remain ignorant on a third. Use item_lca_fit() when the item-specific learning proportions are the target.

The person model currently supports binary responses but not the explicit DK model.

Don't-Know Responses

Observed DK responses select the nine-cell model. Its latent transition parameters are gg, gk, gd, kk, dg, dk, and dd, plus gamma. Learning is gk + dk: learning from a guessing state plus learning from an observed don't-know state.

dk_sim <- simulate_lca_dk(
  n = 1800,
  n_items = 3,
  gg = 0.25,
  gk = 0.15,
  gd = 0.10,
  kk = 0.15,
  dg = 0.10,
  dk = 0.10,
  dd = 0.15,
  gamma = 0.25,
  seed = 789
)

dk_fit <- item_lca_fit(dk_sim$pre, dk_sim$post)
dk_fit$learning
dk_fit$params

Assumptions

The latent class correction relies on assumptions that should be reported with the estimate:

  1. People do not lose item knowledge over the interval. Know-to-guess and know-to-DK transitions are fixed to zero.
  2. A person who knows an item answers it correctly. The current model has no slip parameter.
  3. An item's guessing probability is stable across waves.
  4. Structural missingness is ignorable when incomplete pairs are omitted.
  5. The item-wise model treats items independently. The person model instead imposes one shared trajectory across items.

A correct-to-incorrect response is therefore attributed to guessing rather than knowledge loss. That restriction identifies the learning parameters and should be tested through sensitivity analysis when the interval is long or the content can be forgotten.

Diagnostics

The binary item model is saturated, so it has no residual degrees of freedom for a goodness-of-fit test. The DK model has one over-identifying restriction, and fit_model() reports its Pearson test.

fit_stats <- fit_model(
  dk_sim$pre,
  dk_sim$post,
  g = dk_fit$params["gamma", ],
  est_param = dk_fit$params[-nrow(dk_fit$params), ],
  force9 = TRUE
)

Use held-out likelihood and perplexity to compare predictive performance.

transitions <- multi_transmat(item_sim$pre, item_sim$post)
perplexity_items(item_fit, transitions)
perplexity_individuals(item_fit, item_sim$pre, item_sim$post)
cv_items(transitions, k = 4, seed = 321)
cv_individuals(item_sim$pre, item_sim$post, k = 5, seed = 321)

Validate recovery under sample sizes, item counts, class proportions, and guessing rates that resemble the intended application.

recovery <- validate_recovery(
  c(gg = 0.40, gk = 0.30, kk = 0.30, gamma = 0.25),
  n = 500,
  n_items = 4,
  n_sims = 100,
  seed = 654
)
recovery

Longitudinal IRT

The package does not yet fit a longitudinal IRT model. The planned model will estimate a population ability gain directly, constrain latent mastery to be nondecreasing over the study interval, and retain item-specific guessing. It will be exported separately only after simulation establishes identification, parameter recovery, interval coverage, and agreement with standard longitudinal IRT fits in compatible limiting cases.

Documentation

vignette("using_guess", package = "guess")
vignette("model_validation", package = "guess")

Reference

Cor, K., and G. Sood. 2016. "Guessing and Forgetting: A Latent Class Model for Measuring Learning." Political Analysis 24(2): 226-242.

License

MIT

Copy Link

Version

Install

install.packages('guess')

Monthly Downloads

217

Version

0.7.0

License

MIT + file LICENSE

Issues

Pull Requests

Stars

Forks

Maintainer

Gaurav Sood

Last Published

August 3rd, 2026

Functions in guess (0.7.0)

fit_model

Goodness of fit statistics for transition matrix data
normalize_na_as

Normalize how NA responses are classified
nodk_cell_probs

Cell probabilities for the model without Don't Know
log_likelihood

Calculate log-likelihood for transition data
new_guess_cv

Create a guess_cv object
lca_se

Bootstrapped standard errors of effect size estimates
new_guess_fit

S3 Methods for guess Objects
posterior_learned

Compute posterior probability of learning
nona

Normalize NA Responses
posterior_class_probs

Compute posterior class probabilities
item_lca_fit

Fit Independent Item-Wise LCA Models
guess_lik

guess_lik
normalize_missing_action

Normalize structural missingness handling
guessdk_lik

guessdk_lik
person_item_response_probs

Person/item response probabilities
print.guess_fit

Print method for guess_fit
print.guess_cv

Print method for guess_cv
perplexity_items

Calculate perplexity from aggregated item data
lca_difficulty

Estimate LCA model with a bounded guessing-probability link
validate_required

Validate required parameters are not NULL
lca_cor

Calculate item level and aggregate learning
prepare_response_data

Normalize paired response data frames
person_item_expectation

Person/item EM expectation step
make_guess_lik_difficulty

Create difficulty-parameterized likelihood function (no DK)
summary.guess_fit

Summary method for guess_fit
summary.guess_cv

Summary method for guess_cv
lca_adj

Person Level Adjustment
individual_likelihood_details

Calculate per-individual log-likelihood
validate_subgroup

Validate subgroup parameter
validate_compatible_dataframes

Validate that two data frames have compatible dimensions
transmat

transmat: Cross-wave transition matrix
multi_transmat

Creates a transition matrix for each item.
multinomial_nll

Multinomial negative log-likelihood
validate_gamma

Validate gamma parameter
person_item_lca_fit

Fit a Joint Person-Level Latent Class Model
validate_equal_length

Validate that vectors have equal length
response_to_cell

Map pre/post response pairs to cell indices
interleave

Interleave vectors
person_item_maximization

Person/item EM maximization step
simulate_lca

Simulation Functions for LCA Models
validate_dataframe

Validate that input is a data frame
validate_dk

Validate dk parameter (knowledge behind don't know responses)
stnd_cor

Standard Guessing Correction for Learning
simulate_lca_dk

Simulate Pre-Post Test Data (DK Model)
perplexity_individuals

Calculate perplexity from individual-level data
normalize_responses

Normalize raw item responses
make_guessdk_lik_difficulty

Create difficulty-parameterized likelihood function (DK)
validate_lucky_vector

Validate lucky vector for standard correction
validate_recovery

Validate Parameter Recovery via Monte Carlo Simulation
validate_priors

Validate prior parameters
zero1

Constrain vector to [0,1] range
validate_transition_values

Validate transition matrix values
validate_matrix

Validate matrix input
cross_sectional_learning_score

Cross-Sectional Learning Score
calculate_expected_values

Calculate expected values for goodness of fit test
count_transitions

Count transitions between pre and post test responses
cv_items

K-fold cross-validation over items
cv_individuals

K-fold cross-validation over individuals
coef.guess_fit

Extract coefficients from guess_fit
cross_sectional_learning

Cross-sectional learning estimate
format_transition_matrix

Format transition matrix result with appropriate row and column names
group_adj

Group Level Adjustment That Accounts for Propensity to Guess
estimate_logit_score

Estimate a Cross-Sectional Logit Score
eq1dk

Constraints: Sum to 1
guess-package

guess adjust estimates of learning for guessing related bias.
class_conditional_item

Class-conditional likelihood for single item
eqn1

Sum to 1 constraint (no DK)
dk_cell_probs

Cell probabilities for the model with Don't Know
difficulty_to_gamma

Transform difficulty to gamma
extract_params

Extract parameter matrix from lca_result
gamma_to_difficulty

Transform gamma to difficulty
cell_probs

Model Criticism Tools