You can try to reduce ylim
to the corresponding height:
With random data:
set.seed(123)
testdata <- matrix(rnorm(300), ncol=3)
testcah <- hclust(dist(testdata))
The height for each step of the cah are in testdata$heights
from first to last merge. If, for example, you want 5 groups, you need to know the 4th before last height:
floor_y <- rev(testcah$height)[5-1]
Then, making your object as a dendrogram, you can plot it only on the part you need:
testdend <- as.dendrogram(testcah)
plot(testdend, ylim=c(floor_y, attributes(testdend)$height))
If you want to label the branches with the clusters' labels, as defined by cutree
, you need to get the labels (by reordering cutree
result) and find where to put them along the x axis
. This information can be obtained by "decomposing" the dendrogram to fin the needed midpoints
.
First, get the labels of (all) the leaves:
testlab <- cutree(testcah, 5)[testcah$order]
Then we use a recursive function to find the midpoints of the subdendrograms that lies at the desired height:
find_x <- function(dendro, ordrecah, cutheight){
if(!is.null(attributes(dendro)$leaf)) { # if the dendrogram is a leaf, just get its position in the global dendrogram
return(which(ordrecah==attributes(dendro)$label))
} else {
if(attributes(dendro)$height<cutheight){ # if we're under the height threshold, get the midpoint
return(attributes(dendro)$midpoint)
} else { # if we're above the height threshold, pass the function on the 2 subparts of the dendrogram
return(c(find_x(dendro[[1]], ordrecah, cutheight), find_x(dendro[[2]], ordrecah, cutheight)))
}
}
}
So we can get the midpoints or leaf position with:
test_x <- find_x(testdend, testcah$order, floor_y)
but the midpoints correspond to the distance between the leftmost leaf and the node, so, in case of a cluster with more than one member, we need to add the distance from 1 to the leftmostleaf.
length_clus <- rle(testlab)$lengths # get the number of members by cluster
test_x[length_clus > 1] <- (test_x + head(c(1, cumsum(length_clus)+1), -1))[length_clus > 1]
Finally, put the labels on the plot:
mtext(side=1, at=test_x, line=0, text=unique(testlab))
