Post-clustering inference after hierarchical clustering
Source:R/test.clusters.hc.R
test.clusters.hc.RdPerforms post-clustering inference for the difference between the means of two clusters obtained by hierarchical agglomerative clustering, under a general matrix normal model.
The covariance structure between features Sigma is estimated if not provided, respecting the selective type I error control. The covariance
matrix between observations U is assumed known and should have a compound symmetry structure (see details).
Supported linkage criteria (as in Gao et al. 2022) are "single", "average", "centroid",
"ward.D", "median", "mcquitty", and "complete".
Usage
test.clusters.hc(
X,
U = NULL,
Sigma = NULL,
Y = NULL,
UY = NULL,
precUY = NULL,
NC,
clusters,
linkage = "average",
hcl = NULL,
ndraws = 2000,
sample_split = FALSE,
nY = NULL,
return_Sigma = FALSE,
return_X_clus = FALSE,
dismat = NULL
)Arguments
- X
An \(n \times p\) data matrix assumed to arise from a matrix normal distribution \(\mathcal{MN}(M, U, \Sigma)\).
- U
An \(n \times n\) positive-definite matrix describing the dependence structure between the rows of
X. IfNULL, observations are assumed to be independent andUis set to the \(n \times n\) identity matrix.- Sigma
A \(p \times p\) positive-definite matrix describing the dependence structure between the columns of
X. IfNULL,Sigmais over-estimated from an auxiliary independent sampleY(in the sense of the Loewner partial order).- Y
If
SigmaisNULL, an independent copy ofXused to estimateSigma. It must have the same number of columns asX.- UY
If
SigmaisNULL, an \(n_Y \times n_Y\) positive-definite matrix describing the dependence structure between the rows ofY. IfNULLandprecUYis not provided, the identity matrix is used by default.- precUY
The inverse of
UY. SupplyingprecUYmay improve computational efficiency. IfUYis provided butprecUYisNULL,precUYis computed internally by matrix inversion.- NC
Integer. Number of clusters in the partition obtained by cutting the hierarchical clustering tree.
- clusters
Integer vector of length 2 containing the labels of the two clusters to compare. Its entries must belong to
1:NC.- linkage
Character string specifying the linkage criterion used in hierarchical clustering. Must be one of
"single","average","centroid","ward.D","median","mcquitty", or"complete". Whenhclis provided, the linkage is inferred fromhcl$methodand this argument is overridden. Iflinkageis supplied explicitly alongsidehclbut does not matchhcl$method, a warning is emitted and the method stored inhcltakes precedence.- hcl
An optional precomputed hierarchical clustering object of class
"hclust", as returned byfastcluster::hclust()orstats::hclust()on the squared Euclidean distance matrix ofX. When supplied, the clustering step is skipped and the linkage criterion is inferred fromhcl$method, overriding thelinkageargument. Passing a precomputedhclis useful when testing several cluster pairs from the same clustering, as it avoids recomputing the dendrogram each time. The number of leaves inhclmust equalnrow(X); an error is raised otherwise. Ignored (with a warning) whensample_split = TRUE, because sample splitting changesXafter the clustering would have been computed.- ndraws
Integer. Number of Monte Carlo samples used to approximate the p-value when
linkage = "complete". Ignored otherwise.- sample_split
Logical. Whether to use sample splitting to estimate
SigmawhenSigma = NULL. Ignored whenSigmais provided by the user.- nY
Integer. If
Yis not provided andsample_split = TRUE, the number of rows of the auxiliary sampleYused to estimateSigma. IfnYisNULL, half of the rows ofXare used for estimation. Ignored whenSigmais provided by the user.- return_Sigma
Logical. Whether to include the column covariance matrix used in the test in the returned list. Ignored when
Sigmais provided by the user. Default isFALSE.- return_X_clus
Logical. If sample splitting is performed to estimate
Sigma, whether to include the data matrix used for clustering in the returned list. Ignored whensample_split = FALSE(as the same data matrix is used for clustering and testing). If further analysis of the retrieved clusters is desired, we recommend settingreturn_X_clus = TRUEwhensample_split = TRUEto avoid confusion. Default isFALSE.- dismat
An optional precomputed squared Euclidean distance object of class
"dist", as returned bystats::dist(X, method = "euclidean")^2. When supplied alongsidehcl, both the distance object and the dendrogram computations are skipped, which is useful when testing several cluster pairs from the same clustering. When supplied withouthcl, a warning is emitted and the dendrogram is computed fromdismat. Whenhclis supplied withoutdismatand the linkage is not"complete", a warning is emitted anddismatis recomputed internally. Ignored (with a warning) whensample_split = TRUE, because sample splitting changesXafter the distance object would have been computed.
Value
A named list with the following components:
- pvalue
The p-value for testing equality of the two selected cluster means.
- stat
The observed test statistic.
- stderr
Monte Carlo standard error of the estimated p-value when
linkage = "complete". This component is omitted otherwise.- n_preserved
Number of Monte Carlo samples (out of
ndraws) for whichpreserve.clreturnedTRUE, i.e., the perturbed clustering matched the original cluster labels. Only present whenlinkage = "complete".- S
The truncation set used to compute the p-value when
linkage != "complete". This component is omitted otherwise.- hcl
An integer vector of length \(n\) giving the cluster membership of each observation in the partition with
NCclusters.- Sigma
If return_Sigma = TRUE, the column covariance matrix used in the test, either provided by the user or estimated from
Y.- X_clus
If return_X_clus = TRUE and sample_split = TRUE, the data matrix used for clustering and testing (i.e., the subsample of
Xretained after sample splitting).
Details
Selective type I error control is guaranteed when the row covariance matrix \(\mathbf{U}\) has a compound symmetry (CS) structure, i.e., $$ \mathbf{U} = (a - b)\mathbf{I}_n + b\mathbf{1}_n, $$ for some \(a/(n - 1) < b < a\). In practice, the method is robust to moderate deviations from the CS structure. In particular, reliable performance is typically observed when \(\mathbf{U}\) remains close to CS, for example in autoregressive (AR(1)), diagonal, banded, or Toeplitz covariance structures, depending on their parameters. We therefore recommend applying the method primarily in settings where \(\mathbf{U}\) is known and does not deviate substantially from the compound symmetry structure.
When Sigma = NULL, the column covariance matrix is estimated from an auxiliary independent sample Y. When U = NULL, row-wise independence is assumed.
For linkage criteria other than "complete", the p-value is computed using an exact characterization of the truncation region, adapted from
clusterpval. For "complete" linkage, the truncation region is not computed explicitly and the p-value is approximated by Monte Carlo. In
this case, the Monte Carlo procedure can be automatically parallelized using the future package (see examples).
References
Gao, L. L., Bien, J., and Witten, D. (2022). Selective inference for hierarchical clustering. Journal of the American Statistical Association, 117(540), 2533–2547.
González-Delgado, J., Deronzier, M. Cortés, J., and Neuvial, P. (2023) Post-clustering Inference under Dependence. arXiv.2310.11822.
See also
Other post-clustering inference functions:
test.clusters.MC(),
test.clusters.km()
Examples
n <- 50
p <- 20
# Simulating under the null hypothesis
M <- Matrix::Matrix(0, nrow = n, ncol = p)
Sigma <- stats::toeplitz(seq(1, 0.1, length.out = p))
U <- matrixNormal::I(n)
X <- matrixNormal::rmatnorm(s = 1, M, U, Sigma)
Y <- matrixNormal::rmatnorm(s = 1, M, U, Sigma)
# Hierarchical clustering with average linkage and known Sigma
test.hc <- test.clusters.hc(
X = X, U = U, Sigma = Sigma,
NC = 3, clusters = sample(1:3, 2),
linkage = "average"
)
test.hc$pvalue
#> [1] 0.6363383
# Testing two more cluster pairs reusing the same dendrogram
hcl_obj <- fastcluster::hclust(dist(X)^2, method = "average")
test.hc12 <- test.clusters.hc(
X = X, U = U, Sigma = Sigma,
NC = 3, clusters = c(1, 2), hcl = hcl_obj
)
#> Warning: 'hcl' is provided but 'dismat' is not. The distance matrix will be recomputed internally. Pass 'dismat' as well to avoid recomputing it when testing multiple cluster pairs.
test.hc13 <- test.clusters.hc(
X = X, U = U, Sigma = Sigma,
NC = 3, clusters = c(1, 3), hcl = hcl_obj
)
#> Warning: 'hcl' is provided but 'dismat' is not. The distance matrix will be recomputed internally. Pass 'dismat' as well to avoid recomputing it when testing multiple cluster pairs.
# Hierarchical clustering with complete linkage and estimated Sigma
test.hc <- test.clusters.hc(
X = X, U = U, Sigma = NULL, Y = Y,
NC = 3, clusters = sample(1:3, 2),
linkage = "complete"
)
#> Sigma not provided: plugging an over-estimate.
#> Clustering with complete linkage. Monte-Carlo approximation of the p-value.
test.hc$pvalue
#> [1] 0.07380339
# Hierarchical clustering with complete linkage, estimated Sigma, and parallelization
if (FALSE) { # \dontrun{
library(future)
# Set parallelization plan (adjust workers according to your machine):
plan(multisession, workers = 4)
test.hc <- test.clusters.hc(
X = X, U = U, Sigma = NULL, Y = Y,
NC = 3, clusters = sample(1:3, 2),
linkage = "complete", ndraws = 500
)
test.hc$pvalue
plan(sequential) # Reset to avoid leaving open connections
} # }