% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cluster.test.R
\name{cluster.test}
\alias{cluster.test}
\alias{print.cluster_test}
\alias{as.data.frame.cluster_test}
\title{Cluster heterogeneity diagnostics for QCA configurations}
\usage{
cluster.test(
  data,
  tt,
  cluster_id,
  unit_id = NULL,
  solution = "all",
  include = NULL,
  dir.exp = NULL,
  exclude = NULL,
  which_M = 1,
  i_mode = c("all", "C1P1"),
  necessity = FALSE,
  progress = TRUE,
  ...
)

\method{print}{cluster_test}(x, row.names = FALSE, ...)

\method{as.data.frame}{cluster_test}(x, ...)
}
\arguments{
\item{data}{A data frame object containing the columns used to build
\code{tt} plus the cluster and, optionally, unit identifiers. \code{data}
must have the same number of rows as \code{tt$recoded.data}.}

\item{tt}{A truth table object of class \code{"QCA_tt"}, typically created with
\code{\link[QCA:truthTable]{QCA::truthTable()}}.}

\item{cluster_id}{Name of the column in \code{data} identifying clusters. This
must be a single non-empty character string, and the column must contain
at least two distinct non-missing cluster values.}

\item{unit_id}{Optional name of the column in \code{data} identifying units that
may appear in more than one cluster. If \code{NULL}, units are treated as row
positions and within-unit diagnostics are not available across clusters.}

\item{solution}{Solution type to evaluate. Accepted values are \code{"all"},
\code{"con"} or \code{"conservative"}, \code{"par"} or \code{"parsimonious"}, and \code{"int"} or
\code{"intermediate"}.}

\item{include}{Optional minimization include setting. Currently, this
argument accepts only \code{NULL}, \code{""}, or \code{"?"}.}

\item{dir.exp}{Directional expectations used when the monitored solution is
intermediate. When \code{solution = "all"}, supplying \code{dir.exp} adds
intermediate solutions to the monitored set.}

\item{exclude}{Optional exclusion specification passed to \code{\link[QCA:minimize]{QCA::minimize()}}
for parsimonious and intermediate minimization.}

\item{which_M}{Positive integer giving which solution alternative to use
when minimization returns multiple models.}

\item{i_mode}{Character string controlling intermediate-solution selection.
Accepted values are \code{"all"} and \code{"C1P1"}.}

\item{necessity}{Logical; if \code{TRUE}, compute fit as necessity consistency
and coverage. If \code{FALSE}, compute fit as sufficiency consistency and
coverage.}

\item{progress}{Logical; if \code{TRUE} and the session is interactive, show a
text progress bar while minimizing the monitored solution types.}

\item{...}{Additional arguments. In \code{\link[=cluster.test]{cluster.test()}}, these are filtered and
forwarded to \code{\link[QCA:minimize]{QCA::minimize()}}. The function also looks in \code{...} for
\code{include}, \code{dir.exp} or \code{direxp}, and \code{exclude} or \code{omit} if those
arguments were not supplied explicitly. In \code{\link[=print.cluster_test]{print.cluster_test()}}, \code{...}
is passed to \code{\link[=print.data.frame]{print.data.frame()}}. In
\code{\link[=as.data.frame.cluster_test]{as.data.frame.cluster_test()}}, \code{...} is ignored.}

\item{x}{A \code{cluster_test} object returned by \code{\link[=cluster.test]{cluster.test()}}.}

\item{row.names}{Logical; passed to \code{\link[=print.data.frame]{print.data.frame()}} by
\code{\link[=print.cluster_test]{print.cluster_test()}}.}
}
\value{
An object of class \code{cluster_test} with the following components:
\describe{
\item{\code{diagnostics}}{A detailed data frame with one row per selected
configuration. It records the solution type, configuration key, component count,
status, pooled consistency and coverage, maximum and mean absolute
cluster-level deltas, the clusters with the worst consistency and
coverage values, whether within-unit diagnostics were available, the
number of repeated units, and error information when a configuration could not
be evaluated.}
\item{\code{results}}{A named list with three tables:
\describe{
\item{\code{overview}}{One row per selected configuration, summarizing pooled fit,
maximum cluster deltas, worst clusters, and within-unit
availability.}
\item{\code{clusters}}{One row per configuration-component-cluster combination,
giving cluster-specific consistency, coverage, and deltas from the
pooled configuration values. The whole configuration is stored as
\code{component = "solution"}; separate term-level rows are included only
for multi-term solutions.}
\item{\code{units}}{One row per configuration-component-unit combination for
units observed in more than one cluster, giving within-unit
consistency, coverage, and deltas from the pooled configuration values.
Separate term-level rows are included only for multi-term solutions.}
}}
\item{\code{baseline}}{A list containing the input truth table, minimization
results by solution type, selected solution terms used for comparison,
metadata, and the extracted configuration definitions used for the
heterogeneity diagnostics.}
\item{\code{by_cluster}}{A named list of detailed cluster-level diagnostics
for each selected configuration.}
\item{\code{by_unit}}{A named list of detailed unit-level diagnostics for
each selected configuration when repeated units are available, or \code{NULL}
otherwise.}
\item{\code{settings}}{A list containing the analysis settings used to build
the result object.}
}

\code{print.cluster_test()} prints a compact overview and, when the object has
one displayed configuration, cluster and within-unit details.
\code{as.data.frame.cluster_test()} returns \code{results$overview}.
}
\description{
Evaluates how the consistency and coverage of selected QCA configurations
vary across clusters and, when repeated units are available, across units
observed in more than one cluster. The function starts from an existing
truth table, minimizes it under the requested solution type, extracts the
selected baseline configurations, and then compares pooled fit values with
cluster-specific and within-unit fit values.
}
\details{
The function recovers the outcome membership from \code{tt$recoded.data}, runs
minimization for the requested solution type or solution types, extracts the
selected baseline configurations, and computes pooled fit values for each
configuration and configuration component.

Cluster-level diagnostics compare the pooled fit of each selected
configuration with the fit obtained inside each cluster defined by
\code{cluster_id}.

If \code{unit_id} identifies units that appear in more than one cluster, the
function also computes within-unit diagnostics by comparing the same unit
across clusters.

Configuration extraction uses the data-frame \code{pims} component produced by
\code{\link[QCA:minimize]{QCA::minimize()}}. The shared solution-control, QCA solution-object, and
returned-object conventions are described in \code{?qcaERT_conventions}.
}
\examples{
\donttest{
library(QCA)
data(LR)

conditions <- c("DEV", "URB", "LIT", "IND", "STB")
outcome <- "SURV"
dir_exp <- rep("1", length(conditions))

thresholds <- list(
  DEV = findTh(LR$DEV, groups = 7),
  URB = findTh(LR$URB, groups = 4),
  LIT = findTh(LR$LIT, groups = 4),
  IND = findTh(LR$IND, groups = 4),
  STB = findTh(LR$STB, groups = 4),
  SURV = findTh(LR$SURV, groups = 4)
)

dat <- LR
dat$DEV <- calibrate(LR$DEV, type = "fuzzy", thresholds = thresholds$DEV)
dat$URB <- calibrate(LR$URB, type = "fuzzy", thresholds = thresholds$URB)
dat$LIT <- calibrate(LR$LIT, type = "fuzzy", thresholds = thresholds$LIT)
dat$IND <- calibrate(LR$IND, type = "fuzzy", thresholds = thresholds$IND)
dat$STB <- calibrate(LR$STB, type = "fuzzy", thresholds = thresholds$STB)
dat$SURV <- calibrate(LR$SURV, type = "fuzzy", thresholds = thresholds$SURV)
dat$development_group <- ifelse(
  LR$DEV >= median(LR$DEV, na.rm = TRUE),
  "higher development",
  "lower development"
)
dat$case_id <- rownames(dat)

tt <- truthTable(
  data = dat,
  outcome = outcome,
  conditions = conditions,
  incl.cut = 0.8,
  n.cut = 1,
  complete = TRUE,
  show.cases = TRUE
)
enhanced <- findRows(tt, type = 2)

out <- cluster.test(
  data = dat,
  tt = tt,
  cluster_id = "development_group",
  unit_id = "case_id",
  solution = "intermediate",
  dir.exp = dir_exp,
  exclude = enhanced,
  which_M = 1,
  necessity = FALSE,
  progress = TRUE
)

out
as.data.frame(out)
out$results$clusters
out$results$units
}

}
\seealso{
\code{\link[=calib.test]{calib.test()}}, \code{\link[=incl.test]{incl.test()}}, \code{\link[=ncut.test]{ncut.test()}}, \code{\link[=loo.test]{loo.test()}},
\code{\link[=subsample.test]{subsample.test()}}, \code{\link[=altset.test]{altset.test()}}, \code{\link[=theory.test]{theory.test()}}, \code{\link[=sol.df]{sol.df()}}
}
