% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/Cluster.R
\name{cluster_imputations}
\alias{cluster_imputations}
\title{Perform clustering on multiple imputed datasets}
\usage{
cluster_imputations(
  imp_list,
  method = "ward.D2",
  k,
  scale_data = c("global", "within", "none"),
  distance = c("euclidean", "manhattan", "gower", "jaccard", "simple_matching", "custom"),
  dist_fun = NULL,
  dist_args = list(),
  ...
)
}
\arguments{
\item{imp_list}{A named list of \code{data.frame} objects, as returned by
\code{\link{as_mild_list}}. All datasets must have identical dimensions
and column names.}

\item{method}{A character string specifying the clustering algorithm.
For hierarchical clustering, accepted values are \code{"ward.D"},
\code{"ward.D2"}, \code{"single"}, \code{"complete"}, \code{"average"},
\code{"centroid"}, \code{"median"}, and \code{"mcquitty"}.
Additional options are:
\itemize{
\item \code{"kmeans"}: k-means clustering for numeric data.
\item \code{"pam"}: partitioning around medoids; supports mixed data
when used with \code{distance = "gower"}.
\item \code{"fuzzy"}: fuzzy c-means clustering.
\item \code{"mclust"}: model-based clustering via Gaussian mixtures.
\item \code{"kmodes"}: clustering for purely categorical data.
\item \code{"kprototypes"}: clustering for mixed data (numeric and
categorical).
}
Default is \code{"ward.D2"}.}

\item{k}{A single integer or an integer vector specifying the number of
clusters. If a vector is provided, clustering is performed for each
value of \code{k}.}

\item{scale_data}{Character string specifying the scaling strategy for
continuous numeric variables (binary variables coded as 0/1 are
automatically excluded from scaling). Options are:
\itemize{
\item \code{"global"}: (default) variables are scaled using pooled
mean and standard deviation computed across all imputations
without stacking them in memory (combinatorial variance formula).
Ensures comparability of distance scales between datasets and
is recommended for consensus clustering.
\item \code{"within"}: each imputed dataset is scaled independently
using its own mean and standard deviation. Useful for
exploratory analyses but may introduce inconsistencies in
distance scales across datasets.
\item \code{"none"}: no scaling is applied.
}
Scaling is automatically disabled for \code{distance = "gower"},
\code{"jaccard"}, or \code{"simple_matching"}, and for
\code{method = "kmodes"} and \code{"kprototypes"}, as these handle
variable scales internally.}

\item{distance}{A character string specifying the distance metric used for
hierarchical clustering and \code{method = "pam"}. Options are:
\itemize{
\item \code{"euclidean"}: (default) standard Euclidean distance.
Suitable for continuous numeric data after scaling.
\item \code{"manhattan"}: sum of absolute differences. Suitable for
continuous numeric data; more robust to outliers than Euclidean.
\item \code{"gower"}: Gower distance via \code{cluster::daisy()}.
Supports mixed data types (numeric, categorical, binary).
When used with hierarchical clustering, numeric variables are
normalized using global min/max computed across all imputations,
ensuring cross-imputation comparability. Requires package
\pkg{cluster}.
\item \code{"jaccard"}: Jaccard dissimilarity. Requires all variables
to be binary (0/1 or two-level factor). Requires package
\pkg{proxy}.
\item \code{"simple_matching"}: Simple Matching Coefficient (SMC).
Requires all variables to be binary. Requires package
\pkg{proxy}.
\item \code{"custom"}: user-defined distance function supplied via
\code{dist_fun}. Must return an object of class \code{dist}.
}
Ignored for \code{method = "kmeans"}, \code{"fuzzy"}, \code{"mclust"},
\code{"kmodes"}, and \code{"kprototypes"}, which compute distances
internally.

For \code{method = "pam"}, all distance options are fully supported
as PAM operates on a precomputed dissimilarity matrix.}

\item{dist_fun}{A function that takes a \code{data.frame} and returns a
\code{dist} object. Required when \code{distance = "custom"};
ignored otherwise.}

\item{dist_args}{A named list of additional arguments passed to the distance
function. For \code{distance = "gower"}, arguments are forwarded to
\code{cluster::daisy()}; for \code{distance = "jaccard"} or
\code{"simple_matching"}, to \code{proxy::dist()}; for
\code{distance = "euclidean"} or \code{"manhattan"}, to
\code{stats::dist()}; also for \code{distance = "custom"}. Default is \code{list()}.}

\item{...}{Additional arguments passed to the underlying clustering
function: \code{stats::kmeans}, \code{e1071::cmeans},
\code{mclust::Mclust}, \code{klaR::kmodes}, or
\code{clustMixType::kproto}. Not used for \code{method = "pam"}, which
operates on a precomputed dissimilarity matrix.}
}
\value{
\itemize{
\item If \code{k} is a single value: a named list of integer vectors,
one per imputed dataset, containing the cluster assignment for
each observation.
\item If \code{k} is a vector: a named list of lists, where each
top-level element corresponds to one value of \code{k} (named
\code{"k2"}, \code{"k3"}, etc.), and each inner element is a
named list of cluster assignment vectors, one per imputed dataset.
}
}
\description{
Applies a clustering algorithm to each completed dataset in a standardized
imputation list (as produced by \code{\link{as_mild_list}}). Supports
hierarchical clustering, k-means, PAM, fuzzy c-means, model-based clustering,
k-modes (for categorical data), and k-prototypes (for mixed data).
Accepts a single value of \code{k} or a range, optionally scales the data
prior to clustering, and supports multiple distance metrics including
Gower, Jaccard, Simple Matching Coefficient, and user-defined distances.
}
\details{
\strong{Scaling strategy and cross-imputation comparability:}

For methods that rely on Euclidean or Manhattan distances
(\code{"kmeans"}, \code{"fuzzy"}, \code{"mclust"}, hierarchical with
\code{distance = "euclidean"} or \code{"manhattan"}), \code{scale_data =
"global"} is strongly recommended. It computes the pooled mean and
standard deviation across all imputations using the combinatorial variance
formula — without creating a stacked copy of the data in memory — and
applies the same transformation to every imputation. This ensures that
distances are on the same scale across datasets, which is essential for
a meaningful co-assignment matrix.

Binary variables coded as 0/1 numeric are automatically excluded from
scaling because standardizing them loses their binary semantics.

\strong{Gower distance and global normalization:}

Gower distance normalizes each numeric variable by its range. When
computed independently per imputation, different imputations may produce
slightly different ranges, leading to incomparable distance scales. When
\code{distance = "gower"} is used with hierarchical clustering or PAM,
the function pre-normalizes numeric variables using global min/max
computed across all imputations (without stacking), so that Gower
distances are on a consistent scale across datasets. Categorical and
factor variables are left untouched and handled normally by
\code{cluster::daisy()}. Additional arguments to \code{cluster::daisy()}
can be passed via \code{dist_args}.

\strong{Hierarchical clustering optimization:}

When \code{method} is hierarchical and \code{k} is a vector, the
distance matrix and dendrogram are computed only once per imputed dataset
and then cut at each requested \code{k}, which avoids redundant
computation.

\strong{Data type compatibility:}
\itemize{
\item Numeric-only: hierarchical, \code{"kmeans"}, \code{"fuzzy"},
\code{"mclust"}.
\item Categorical-only: \code{"kmodes"}.
\item Mixed (numeric + categorical): \code{"pam"} with
\code{distance = "gower"} or \code{"kprototypes"}.
\item Binary-only: hierarchical with \code{distance = "jaccard"} or
\code{"simple_matching"}.
}

Character variables are internally converted to factors.
}
\examples{
# ------------------------------------------------------------
# Example 1: Numeric data, hierarchical clustering
# ------------------------------------------------------------
set.seed(123)
imp_list <- replicate(3, {
  data.frame(x = rnorm(20), y = rnorm(20))
}, simplify = FALSE)

# Single k, global scaling, euclidean distance (default)
res <- cluster_imputations(imp_list, method = "ward.D2", k = 2)
str(res)

# Range of k, manhattan distance
res_multi <- cluster_imputations(imp_list, method = "ward.D2",
                                 k = 2:4, distance = "manhattan")
str(res_multi)

# ------------------------------------------------------------
# Example 2: Mixed data, PAM with Gower distance
# ------------------------------------------------------------
set.seed(123)
imp_mixed <- replicate(3, {
  data.frame(
    x    = rnorm(20),
    grup = factor(sample(letters[1:3], 20, replace = TRUE))
  )
}, simplify = FALSE)

res_pam <- cluster_imputations(imp_mixed, method = "pam",
                               k = 2, distance = "gower")
str(res_pam)

# ------------------------------------------------------------
# Example 3: Binary data, Jaccard distance
# ------------------------------------------------------------
set.seed(123)
imp_bin <- replicate(3, {
  data.frame(
    a = sample(0:1, 20, replace = TRUE),
    b = sample(0:1, 20, replace = TRUE),
    c = sample(0:1, 20, replace = TRUE)
  )
}, simplify = FALSE)

\donttest{
if (requireNamespace("proxy", quietly = TRUE)) {
  res_jac <- cluster_imputations(imp_bin, method = "ward.D2",
                                 k = 2, distance = "jaccard")
  str(res_jac)
}

# ------------------------------------------------------------
# Example 4: Full pipeline with mice
# ------------------------------------------------------------
if (requireNamespace("mice", quietly = TRUE)) {

  df_pre       <- mice::nhanes
  df_pre$age   <- factor(df_pre$age)
  df_pre$hyp   <- factor(df_pre$hyp)

  imp  <- mice::mice(df_pre, m = 3, printFlag = FALSE, seed = 123)
  mild <- as_mild_list(imp)

  # PAM + Gower with global range normalization
  parts <- cluster_imputations(mild, method = "pam",
                               k = 2:4, distance = "gower")
  str(parts)
}
}

}
\references{
Kaufman, L., & Rousseeuw, P. J. (1990).
\emph{Finding Groups in Data: An Introduction to Cluster Analysis}. Wiley.
\doi{10.1002/9780470316801}

Bezdek, J. C. (1981).
\emph{Pattern Recognition with Fuzzy Objective Function Algorithms}.
Plenum Press.

Huang, Z. (1998).
Extensions to the k-means algorithm for clustering large data sets
with categorical values.
\emph{Data Mining and Knowledge Discovery}, \strong{2}(3), 283-304.
\doi{10.1023/A:1009769707641}

Gower, J. C. (1971).
A general coefficient of similarity and some of its properties.
\emph{Biometrics}, \strong{27}(4), 857-871.
\doi{10.2307/2528823}

Scrucca, L., Fop, M., Murphy, T. B., & Raftery, A. E. (2016).
mclust 5: Clustering, classification and density estimation using
Gaussian finite mixture models.
\emph{The R Journal}, \strong{8}(1), 289-317.
\doi{10.32614/RJ-2016-021}
}
\seealso{
\code{\link{as_mild_list}}, \code{\link{consensus_clustering}}
}
