% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/latent_corr.R
\name{polychoric}
\alias{polychoric}
\alias{print.polychoric_corr}
\alias{plot.polychoric_corr}
\alias{summary.polychoric_corr}
\alias{print.summary.polychoric_corr}
\title{Pairwise Polychoric Correlation}
\usage{
polychoric(
  data,
  y = NULL,
  na_method = c("error", "pairwise"),
  ci = FALSE,
  p_value = FALSE,
  conf_level = 0.95,
  correct = 0.5,
  output = c("matrix", "sparse", "edge_list"),
  threshold = 0,
  diag = TRUE,
  ...
)

\method{print}{polychoric_corr}(
  x,
  digits = 4,
  n = NULL,
  topn = NULL,
  max_vars = NULL,
  width = NULL,
  show_ci = NULL,
  ...
)

\method{plot}{polychoric_corr}(
  x,
  title = "Polychoric correlation heatmap",
  low_color = "indianred1",
  high_color = "steelblue1",
  mid_color = "white",
  value_text_size = 4,
  show_value = TRUE,
  ...
)

\method{summary}{polychoric_corr}(
  object,
  n = NULL,
  topn = NULL,
  max_vars = NULL,
  width = NULL,
  ci_digits = 3,
  p_digits = 4,
  show_ci = NULL,
  ...
)

\method{print}{summary.polychoric_corr}(
  x,
  digits = NULL,
  n = NULL,
  topn = NULL,
  max_vars = NULL,
  width = NULL,
  show_ci = NULL,
  ...
)
}
\arguments{
\item{data}{An ordinal vector, matrix, or data frame. Supported columns are
factors, ordered factors, logical values, or integer-like numerics.
In matrix/data-frame mode, only supported ordinal columns are retained.}

\item{y}{Optional second ordinal vector. When supplied, the function returns
a single polychoric correlation estimate.}

\item{na_method}{Character scalar controlling missing-data handling.
\code{"error"} rejects missing values. \code{"pairwise"} uses pairwise
complete cases.}

\item{ci}{Logical (default \code{FALSE}). If \code{TRUE}, attach
model-based large-sample Wald confidence intervals derived from the observed
information matrix of the latent-variable likelihood.}

\item{p_value}{Logical (default \code{FALSE}). If \code{TRUE}, attach
model-based large-sample Wald p-values and test statistics for each
estimated latent correlation.}

\item{conf_level}{Confidence level used when \code{ci = TRUE}. Default is
\code{0.95}.}

\item{correct}{Non-negative continuity correction added to zero-count cells.
Default is \code{0.5}.}

\item{output}{Output representation for the computed estimates.
\itemize{
\item \code{"matrix"} (default): full dense matrix; best when you need
matrix algebra, dense heatmaps, or full compatibility with existing code.
\item \code{"sparse"}: sparse matrix from \pkg{Matrix} containing only
retained entries; best when many values are dropped by thresholding.
\item \code{"edge_list"}: long-form data frame with columns
\code{row}, \code{col}, \code{value}; convenient for filtering, joins,
and network-style workflows.
}}

\item{threshold}{Non-negative absolute-value filter for non-matrix outputs:
keep entries with \code{abs(value) >= threshold}. Use
\code{threshold > 0} when you want only stronger associations (typically
with \code{output = "sparse"} or \code{"edge_list"}). Keep
\code{threshold = 0} to retain all values. Must be \code{0} when
\code{output = "matrix"}.}

\item{diag}{Logical; whether to include diagonal entries in
\code{"sparse"} and \code{"edge_list"} outputs.}

\item{...}{Additional arguments passed to \code{print()}.}

\item{x}{An object of class \code{summary.polychoric_corr}.}

\item{digits}{Integer; number of decimal places to print.}

\item{n}{Optional row threshold for compact preview output.}

\item{topn}{Optional number of leading/trailing rows to show when truncated.}

\item{max_vars}{Optional maximum number of visible columns; \code{NULL} derives this
from console width.}

\item{width}{Optional display width; defaults to \code{getOption("width")}.}

\item{show_ci}{One of \code{"yes"} or \code{"no"}.}

\item{title}{Plot title. Default is \code{"Polychoric correlation heatmap"}.}

\item{low_color}{Color for the minimum correlation.}

\item{high_color}{Color for the maximum correlation.}

\item{mid_color}{Color for zero correlation.}

\item{value_text_size}{Font size used in tile labels.}

\item{show_value}{Logical; if \code{TRUE} (default), overlay numeric values
on the heatmap tiles.}

\item{object}{An object of class \code{polychoric_corr}.}

\item{ci_digits}{Integer; digits for confidence limits in the pairwise
summary.}

\item{p_digits}{Integer; digits for p-values in the pairwise summary.}
}
\value{
If \code{y} is supplied, a numeric scalar with attributes
\code{diagnostics} and \code{thresholds}. Otherwise a symmetric matrix of
class \code{polychoric_corr} with attributes \code{method},
\code{description}, \code{package = "matrixCorr"}, \code{diagnostics},
\code{thresholds}, and \code{correct}. When \code{p_value = TRUE}, the
returned object also carries an \code{inference} attribute with elements
\code{estimate}, \code{statistic}, \code{parameter}, \code{p_value}, and
\code{n_obs}. When \code{ci = TRUE}, it also carries a \code{ci} attribute
with elements \code{est}, \code{lwr.ci}, \code{upr.ci}, \code{conf.level},
and \code{ci.method}, plus \code{attr(x, "conf.level")}. Scalar outputs keep
the same point estimate and gain the same metadata only when inference is
requested. In matrix mode, \code{output = "edge_list"} returns a data frame with columns
\code{row}, \code{col}, \code{value}; \code{output = "sparse"} returns a
symmetric sparse matrix.
}
\description{
Computes the polychoric correlation for either a pair of ordinal variables
or all pairwise combinations of ordinal columns in a matrix/data frame.
}
\details{
The polychoric correlation generalises the tetrachoric model to ordered
categorical variables with more than two levels. It assumes latent
standard-normal variables \eqn{Z_1, Z_2} with correlation \eqn{\rho}, and
cut-points
\eqn{-\infty = \alpha_0 < \alpha_1 < \cdots < \alpha_R = \infty} and
\eqn{-\infty = \beta_0 < \beta_1 < \cdots < \beta_C = \infty} such that
\deqn{
X = r \iff \alpha_{r-1} < Z_1 \le \alpha_r,
\qquad
Y = c \iff \beta_{c-1} < Z_2 \le \beta_c.
}
For an observed \eqn{R \times C} contingency table with counts \eqn{n_{rc}},
the thresholds are estimated from the marginal cumulative proportions:
\deqn{
\alpha_r = \Phi^{-1}\!\Big(\sum_{k \le r} P(X = k)\Big),
\qquad
\beta_c = \Phi^{-1}\!\Big(\sum_{k \le c} P(Y = k)\Big).
}
Holding those thresholds fixed, the log-likelihood for the latent
correlation is
\deqn{
\ell(\rho) = \sum_{r=1}^{R}\sum_{c=1}^{C}
n_{rc} \log \Pr\!\big(
\alpha_{r-1} < Z_1 \le \alpha_r,\;
\beta_{c-1} < Z_2 \le \beta_c
\mid \rho \big),
}
and the estimator returned is the maximiser over \eqn{\rho \in (-1,1)}.
The C++ implementation performs a dense one-dimensional search followed by
Brent refinement.

The argument \code{correct} adds a non-negative continuity correction to
empty cells before marginal threshold estimation and likelihood evaluation.
This avoids numerical failures for sparse tables with structurally zero cells.
When \code{correct = 0} and zero cells are present, the corresponding fit can
be boundary-driven rather than a regular interior maximum-likelihood problem.
The returned object stores sparse-fit diagnostics and the thresholds used for
estimation so those cases can be inspected explicitly.

\strong{Assumptions.} The coefficient is appropriate when both observed
ordinal variables are viewed as discretisations of jointly normal latent
variables. The optional p-values and confidence intervals adopt this
latent-normal interpretation and use the same likelihood that defines the
polychoric estimate. These inferential quantities are therefore model-based
and should not be interpreted as distribution-free summaries.

\strong{Inference.} When \code{ci = TRUE} or \code{p_value = TRUE}, the
function refits the pairwise polychoric model by maximum likelihood and
obtains the observed information matrix numerically in C++. The reported
confidence interval is a Wald interval
\eqn{\hat\rho \pm z_{1-\alpha/2}\operatorname{SE}(\hat\rho)}, and the
reported p-value is from the large-sample Wald \eqn{z}-test for
\eqn{H_0:\rho = 0}. These inferential quantities are only computed when
explicitly requested.

In matrix/data-frame mode, all pairwise polychoric correlations are computed
between supported ordinal columns. Diagonal entries are \code{1} for
non-degenerate columns and \code{NA} when a column has fewer than two
observed levels.

\strong{Computational complexity.} For \eqn{p} ordinal variables, the matrix
path evaluates \eqn{p(p-1)/2} bivariate likelihoods. Each pair optimises a
single scalar parameter \eqn{\rho}, so the main cost is repeated evaluation
of bivariate normal rectangle probabilities.
}
\examples{
\dontshow{if (requireNamespace("mnormt", quietly = TRUE)) withAutoprint(\{ # examplesIf}
set.seed(124)
n <- 1200
Sigma <- matrix(c(
  1.00, 0.60, 0.40,
  0.60, 1.00, 0.50,
  0.40, 0.50, 1.00
), 3, 3, byrow = TRUE)

Z <- mnormt::rmnorm(n = n, mean = rep(0, 3), varcov = Sigma)
Y <- data.frame(
  y1 = ordered(cut(
    Z[, 1],
    breaks = c(-Inf, -0.7, 0.4, Inf),
    labels = c("low", "mid", "high")
  )),
  y2 = ordered(cut(
    Z[, 2],
    breaks = c(-Inf, -1.0, -0.1, 0.8, Inf),
    labels = c("1", "2", "3", "4")
  )),
  y3 = ordered(cut(
    Z[, 3],
    breaks = c(-Inf, -0.4, 0.2, 1.1, Inf),
    labels = c("A", "B", "C", "D")
  ))
)

pc <- polychoric(Y)
print(pc, digits = 3)
summary(pc)
estimate(pc)
tidy(pc)
pc_ci <- polychoric(Y, ci = TRUE)
ci(pc_ci)
confint(pc_ci)
plot(pc)
polychoric(Y, output = "edge_list", threshold = 0.3, diag = FALSE)

# Interactive viewing (requires shiny)
if (interactive() && requireNamespace("shiny", quietly = TRUE)) {
  view_corr_shiny(pc)
}

# latent Pearson correlations used to generate the ordinal variables
round(stats::cor(Z), 2)
\dontshow{\}) # examplesIf}
}
\references{
Olsson, U. (1979). Maximum likelihood estimation of the polychoric
correlation coefficient. \emph{Psychometrika}, 44(4), 443-460.
}
\author{
Thiago de Paula Oliveira
}
