% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/api-tables.R
\name{unexpected_response_table}
\alias{unexpected_response_table}
\title{Build an unexpected-response screening report}
\usage{
unexpected_response_table(
  fit,
  diagnostics = NULL,
  abs_z_min = 2,
  prob_max = 0.3,
  top_n = 100,
  rule = c("either", "both")
)
}
\arguments{
\item{fit}{Output from \code{\link[=fit_mfrm]{fit_mfrm()}}.}

\item{diagnostics}{Optional output from \code{\link[=diagnose_mfrm]{diagnose_mfrm()}}.}

\item{abs_z_min}{Absolute standardized-residual cutoff.}

\item{prob_max}{Maximum observed-category probability cutoff.}

\item{top_n}{Maximum number of rows to return.}

\item{rule}{Flagging rule: \code{"either"} (default) or \code{"both"}.}
}
\value{
A named list with:
\itemize{
\item \code{table}: flagged response rows
\item \code{summary}: one-row overview
\item \code{thresholds}: applied thresholds
}
}
\description{
Build an unexpected-response screening report
}
\details{
A response is flagged as unexpected when:
\itemize{
\item \code{rule = "either"}: \verb{|StdResidual| >= abs_z_min} OR \code{ObsProb <= prob_max}
\item \code{rule = "both"}: both conditions must be met.
}

The table includes row-level observed/expected values, residuals,
observed-category probability, most-likely category, and a composite
severity score for sorting.
}
\section{Interpreting output}{

\itemize{
\item \code{summary}: prevalence of unexpected responses under current thresholds.
\item \code{table}: ranked row-level diagnostics for case review.
\item \code{thresholds}: active cutoffs and flagging rule.
}

Compare results across \code{rule = "either"} and \code{rule = "both"} to assess how
conservative your screening should be.
}

\section{Typical workflow}{

\enumerate{
\item Start with \code{rule = "either"} for broad screening.
\item Re-run with \code{rule = "both"} for strict subset.
\item Inspect top rows and visualize with \code{\link[=plot_unexpected]{plot_unexpected()}}.
}
}

\section{Further guidance}{

For a plot-selection guide and a longer walkthrough, see
\link{mfrmr_visual_diagnostics} and
\code{vignette("mfrmr-visual-diagnostics", package = "mfrmr")}.
}

\section{Output columns}{

The \code{table} data.frame contains:
\describe{
\item{Row}{Original row index in the prepared data.}
\item{Person}{Person identifier (plus one column per facet).}
\item{Score}{Observed score category.}
\item{Observed, Expected}{Observed and model-expected score values.}
\item{Residual, StdResidual}{Raw and standardized residuals.}
\item{ObsProb}{Probability of the observed category under the model.}
\item{MostLikely, MostLikelyProb}{Most probable category and its
probability.}
\item{Severity}{Composite severity index (higher = more unexpected).}
\item{Direction}{"Higher than expected" or "Lower than expected".}
\item{FlagLowProbability, FlagLargeResidual}{Logical flags for each
criterion.}
}

The \code{summary} data.frame contains:
\describe{
\item{TotalObservations}{Total observations analyzed.}
\item{UnexpectedN, UnexpectedPercent}{Count and share of flagged rows.}
\item{AbsZThreshold, ProbThreshold}{Applied cutoff values.}
\item{Rule}{"either" or "both".}
}
}

\examples{
toy_full <- load_mfrmr_data("example_core")
toy_people <- unique(toy_full$Person)[1:12]
toy <- toy_full[toy_full$Person \%in\% toy_people, , drop = FALSE]
fit <- suppressWarnings(
  fit_mfrm(toy, "Person", c("Rater", "Criterion"), "Score", method = "JML", maxit = 30)
)
t4 <- unexpected_response_table(fit, abs_z_min = 1.5, prob_max = 0.4, top_n = 5)
summary(t4)
p_t4 <- plot(t4, draw = FALSE)
p_t4$data$plot
}
\seealso{
\code{\link[=diagnose_mfrm]{diagnose_mfrm()}}, \code{\link[=displacement_table]{displacement_table()}}, \code{\link[=fair_average_table]{fair_average_table()}},
\link{mfrmr_visual_diagnostics}
}
