blob: 0093ca4c35f2b19f9f5a917ffffbcefce8b347c0 [file] [log] [blame]
# File src/library/stats/R/identify.hclust.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2012 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
rect.hclust <- function(tree, k=NULL, which=NULL,
x=NULL, h=NULL, border=2, cluster=NULL)
{
if(length(h) > 1L | length(k) > 1L)
stop("'k' and 'h' must be a scalar")
if(!is.null(h)){
if(!is.null(k))
stop("specify exactly one of 'k' and 'h'")
k <- min(which(rev(tree$height)<h))
k <- max(k, 2)
}
else
if(is.null(k))
stop("specify exactly one of 'k' and 'h'")
if(k < 2 | k > length(tree$height))
stop(gettextf("k must be between 2 and %d", length(tree$height)),
domain = NA)
if(is.null(cluster))
cluster <- cutree(tree, k=k)
## cutree returns classes sorted by data, we need classes
## as occurring in the tree (from left to right)
clustab <- table(cluster)[unique(cluster[tree$order])]
m <- c(0, cumsum(clustab))
if(!is.null(x)){
if(!is.null(which))
stop("specify exactly one of 'which' and 'x'")
which <- x
for(n in seq_along(x))
which[n] <- max(which(m<x[n]))
}
else
if(is.null(which))
which <- 1L:k
if(any(which>k))
stop(gettextf("all elements of 'which' must be between 1 and %d", k),
domain = NA)
border <- rep_len(border, length(which))
retval <- list()
for(n in seq_along(which)) {
rect(m[which[n]]+0.66, par("usr")[3L],
m[which[n]+1]+0.33, mean(rev(tree$height)[(k-1):k]),
border = border[n])
retval[[n]] <- which(cluster==as.integer(names(clustab)[which[n]]))
}
invisible(retval)
}
identify.hclust <- function(x, FUN = NULL, N = 20, MAXCLUSTER = 20,
DEV.FUN = NULL, ...)
{
cluster <- cutree(x, k = 2:MAXCLUSTER)
retval <- list()
oldk <- NULL
oldx <- NULL
DEV.x <- dev.cur()
for(n in 1L:N){
dev.set(DEV.x)
X <- locator(1)
if(is.null(X))
break
k <- min(which(rev(x$height) < X$y), MAXCLUSTER)
k <- max(k, 2)
if(!is.null(oldx)){
rect.hclust(x, k = oldk, x = oldx, cluster = cluster[, oldk-1],
border = "grey")
}
retval[[n]] <- unlist(rect.hclust(x, k = k, x = X$x,
cluster = cluster[, k-1],
border = "red"))
if(!is.null(FUN)){
if(!is.null(DEV.FUN)){
dev.set(DEV.FUN)
}
retval[[n]] <- FUN(retval[[n]], ...)
}
oldx <- X$x
oldk <- k
}
dev.set(DEV.x)
invisible(retval)
}