R rect.hclust: rectangles too high in dendogram - r

I asked a number of different experts to sort 92 objects based on their similarity. Based on their answers, I constructed a 92 x 92 dissimilarity matrix. in R, I examined this matrix using the following commands:
cluster1 <- hclust(as.dist(DISS_MATRIX), method = "average")
plot(cluster1, cex=.55)
To highlight the clusters, I wanted to draw rectangles around them:
rect.hclust(cluster1, k = 3, border = "red")
The result is as follows:
However, when the objects have longer names ("AAAAAAAAAAAAAAAA43" instead of "A43") then the formating is off:
rownames(DISS_MATRIX) <- paste0(rep("AAAAAAAAAAAAAAAAAAAAAAAAAAAA",92),1:92)
colnames(DISS_MATRIX) <- paste0(rep("AAAAAAAAAAAAAAAAAAAAAAAAAAAA",92),1:92)
cluster1 <- hclust(as.dist(DISS_MATRIX), method = "average")
plot(cluster1, cex=.55)
rect.hclust(cluster1, k = 3, border = "red")
This can be seen by the resulting dendogram.
The rectangles seem to have moved up to the end of the dendogram. Not nice. I assume this glitch must have been due to the long names of 92 objects in the dissimilarity matrix. It may also not seem very relevant. Just make sure your objects have names short enough.
However, due to different reasons I want my objects to have their original (i.e.admittedly long) names. This graph is for a presentation and thus I do not want to work with codes. I also do not want to use any other package since I generally find hclust quite easy to use. However, I do not find any way to position rectangles within the rect.hclust command. Hence, what can I do to position the rectangles into the dendogram even if object names are long? Thanks.

You wrote that "I also do not want to use any other package since I generally find hclust quite easy to use."
While hclust is great for creating the hierarchical clustering object it does not support much in terms of plotting. Once you have the hclust output, it is better to change it to dendrogram (using as.dendrogram) for visualizations (since it is better suited for that). There is no way to do what you want without using sophisticated code, which is packed in a package, this is the best route (IMHO) for you to move forward. (I know because I wrote rect.dendrogram, and it took a lot of work to get it to work the way you want it)
The dendextend R package allows many functions for manipulating and visualizing dendrograms (see the vignette here).
Specifically, the rect.dendrogram function can handle such cases as you asked about (with having long labels). For example (I've added color_branches and color_labels for the fun of it):
library(dendextend)
hc <- mtcars[, c("mpg", "disp")] %>% dist %>% hclust(method = "average")
dend <- hc %>% as.dendrogram %>% hang.dendrogram
# let's make the text longer
labels(dend)[1] <- "AAAAAAAAAAAAAAAAAAAAA"
par(mar = c(15,2,1,1))
dend %>% color_branches(k=3) %>% color_labels(k=3) %>% plot
dend %>% rect.dendrogram(k=3)

Related

iGraph - Spacing between verticies

I have a dataset called data. The data is not that important, but every interaction has a name. I want to create a graph in iGraph with the following code:
tab <- count(data, B, S, K)
factors <- table(interaction(tab$B, tab$K),interaction(tab$S,tab$K))
graph1 <- graph_from_incidence_matrix(factors)
plot(graph1, vertex.size = 40, layout = layout.bipartite)
However, I get the following:
All the names of interactions are completely mixed together. I can make it a little more readable by lowering the vertex.size, but I want to find a solution to my problem.
I want to create more space between the verticies, but I cannot seem to find the right way.
I have tried creating a manual graph by using tkplot, but it is annoying that I manually have to sort them each time.
Best regards

How to get individually made dendrograms from dendextend to consesnus tree analysis?

I am pretty new to R so I am struggling with the following:
I have a dataset where I am clustering several organ`s expresion values per patient. Like this I build 10 individual dendrograms. NOW, I would like to perform a consensus analysis and see how these individually built trees agree.
For the individual trees I have been using dendextend package. And I wanted to use the ape consensus function but I dont know how to transform my outcome from dendextend such that it is accepted in the consensus.
Like this I can plot the 10 individual trees
dend <- RawData[,4:ncol(RawData)] %>%
dist %>%
hclust(method = "average")%>%
as.dendrogram
labels(dend) <- TMA_TT
dev.new()
dend %>% plot(main="dend")
I d like to use this:
consensus(..., p = 1, check.labels = TRUE)
....either (i) a single object of class "phylo", (ii) a series of such objects separated by commas, or (iii) a list containing such objects.
But I am not sure how to get my dendextend results to this format.

How to cut a dendrogram in r

Okay so I'm sure this has been asked before but I can't find a nice answer anywhere after many hours of searching.
I have some data, I run a classification then I make a dendrogram.
The problem has to do with aesthetics, specifically; (1) how to cut according to the number of groups (in this example I want 3), (2) make the group labels aligned with the branches of the trees, (2) Re-scale so that there aren't any huge gaps between the groups
More on (3). I have dataset which is very species rich and there would be ~1000 groups without cutting. If I cut at say 3, the tree has some branches on the right and one 'miles' off to the right which I would want to re-scale so that its closer. All of this is possible via external programs but I want to do it all in r!
Bonus points if you can put an average silhouette width plot nested into the top right of this plot
Here is example using iris data
library(ggplot2)
data(iris)
df = data.frame(iris)
df$Species = NULL
ED10 = vegdist(df,method="euclidean")
EucWard_10 = hclust(ED10,method="ward.D2")
hcd_ward10 = as.dendrogram(EucWard_10)
plot(hcd_ward10)
plot(cut(hcd_ward10, h = 10)$upper, main = "Upper tree of cut at h=75")
I suspect what you would want to look at is the dendextend R package (it also has a paper in bioinformatics).
I am not fully sure about your question on (3), since I am not sure I understand what rescaling means. What I can tell you is that you can do quite a lot of dendextend. Here is a quick example for coloring the branches and labels for 3 groups.
library(ggplot2)
library(vegan)
data(iris)
df = data.frame(iris)
df$Species = NULL
library(vegan)
ED10 = vegdist(df,method="euclidean")
EucWard_10 = hclust(ED10,method="ward.D2")
hcd_ward10 = as.dendrogram(EucWard_10)
plot(hcd_ward10)
install.packages("dendextend")
library(dendextend)
dend <- hcd_ward10
dend <- color_branches(dend, k = 3)
dend <- color_labels(dend, k = 3)
plot(dend)
You can also get an interactive dendrogram by using plotly (ggplot method is available through dendextend):
library(plotly)
library(ggplot2)
p <- ggplot(dend)
ggplotly(p)

How to make R output text details about a dendrogram object?

Please see my previous question for details relating to test data and commands used to create a dendrogram: Using R to cluster based on euclidean distance and a complete linkage metric, too many vectors?
Here is a quick summary of my commands to make the dendrogram:
un_exprs <- as.matrix(read.table("sample.txt", header=TRUE, sep = "\t", row.names = 1, as.is=TRUE))
exprs <- t(un_exprs)
eucl_dist=dist(exprs,method = 'euclidean')
hie_clust=hclust(eucl_dist, method = 'complete')\
dend <- as.dendrogram(hie_clust)
plot(dend)
This makes a very nice dengrogram plot. However, lets say this dendrogram has 2 clusters... I want to get a text list of each element belonging to each of the 2 clusters. I'm assuming this is trivial, but I don't have enough experience with R for this to be intuitive. Thanks!
You can compute this from the hclust return with stats::cutree
cutree(hie_clust,k=2)

Node labels on circular phylogenetic tree

I am trying to create circular phylogenetic tree. I have this part of code:
fit<- hclust(dist(Data[,-4]), method = "complete", members = NULL)
nclus= 3
color=c('red','blue','green')
color_list=rep(color,nclus/length(color))
clus=cutree(fit,nclus)
plot(as.phylo(fit),type='fan',tip.color=color_list[clus],label.offset=0.2,no.margin=TRUE, cex=0.70, show.node.label = TRUE)
And this is result:
Also I am trying to show label for each node and to color branches. Any suggestion how to do that?
Thanks!
When you say "color branches" I assume you mean color the edges. This seems to work, but I have to think there's a better way.
Using the built-in mtcars dataset here, since you did not provide your data.
plot.fan <- function(hc, nclus=3) {
palette <- c('red','blue','green','orange','black')[1:nclus]
clus <-cutree(hc,nclus)
X <- as.phylo(hc)
edge.clus <- sapply(1:nclus,function(i)max(which(X$edge[,2] %in% which(clus==i))))
order <- order(edge.clus)
edge.clus <- c(min(edge.clus),diff(sort(edge.clus)))
edge.clus <- rep(order,edge.clus)
plot(X,type='fan',
tip.color=palette[clus],edge.color=palette[edge.clus],
label.offset=0.2,no.margin=TRUE, cex=0.70)
}
fit <- hclust(dist(mtcars[,c("mpg","hp","wt","disp")]))
plot.fan(fit,3); plot.fan(fit,5)
Regarding "label the nodes", if you mean label the tips, it looks like you've already done that. If you want different labels, unfortunately, unlike plot.hclust(...) the labels=... argument is rejected. You could experiment with the tiplabels(....) function, but it does not seem to work very well with type="fan". The labels come from the row names of Data, so your best bet IMO is to change the row names prior to clustering.
If you actually mean label the nodes (the connection points between the edges, have a look at nodelabels(...). I don't provide a working example because I can't imagine what labels you would put there.

Resources