blob: eb6969a3b44d4a2003376d5f7864f02c59cc0846 [file] [log] [blame]
# File src/library/stats/R/cutree.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/
cutree <- function(tree, k=NULL, h=NULL)
{
if(is.null(n1 <- nrow(tree$merge)) || n1 < 1)
stop("invalid 'tree' ('merge' component)")
n <- n1 + 1
if(is.null(k) && is.null(h))
stop("either 'k' or 'h' must be specified")
if(is.null(k)) {
if(is.unsorted(tree$height))
stop("the 'height' component of 'tree' is not sorted (increasingly)")
## h |--> k
## S+6 help(cutree) says k(h) = k(h+), but does k(h-) [continuity]
## h < min() should give k = n;
k <- n+1L - apply(outer(c(tree$height,Inf), h, ">"), 2, which.max)
if(getOption("verbose")) message("cutree(): k(h) = ", k, domain = NA)
}
else {
k <- as.integer(k)
if(min(k) < 1 || max(k) > n)
stop(gettextf("elements of 'k' must be between 1 and %d", n),
domain = NA)
}
ans <- .Call(C_cutree, tree$merge, k)
if(length(k) == 1L) {
ans <- setNames(as.vector(ans), tree$labels)
}
else{
colnames(ans) <- if(!is.null(h)) h else k
rownames(ans) <- tree$labels
}
return(ans)
}