web-dev-qa-db-fra.com

Tracer une carte thermique en cluster avec des dendrogrammes à l'aide de R

Je suis cet exemple sur la façon de créer une carte thermique en cluster avec des dendrogrammes avec R de plotly. Voici l'exemple:

library(ggplot2)
library(ggdendro)
library(plotly)

#dendogram data
x <- as.matrix(scale(mtcars))
dd.col <- as.dendrogram(hclust(dist(x)))
dd.row <- as.dendrogram(hclust(dist(t(x))))
dx <- dendro_data(dd.row)
dy <- dendro_data(dd.col)

# helper function for creating dendograms
ggdend <- function(df) {
  ggplot() +
    geom_segment(data = df, aes(x=x, y=y, xend=xend, yend=yend)) +
    labs(x = "", y = "") + theme_minimal() +
    theme(axis.text = element_blank(), axis.ticks = element_blank(),
          panel.grid = element_blank())
}

# x/y dendograms
px <- ggdend(dx$segments)
py <- ggdend(dy$segments) + coord_flip()

# heatmap
col.ord <- order.dendrogram(dd.col)
row.ord <- order.dendrogram(dd.row)
xx <- scale(mtcars)[col.ord, row.ord]
xx_names <- attr(xx, "dimnames")
df <- as.data.frame(xx)
colnames(df) <- xx_names[[2]]
df$car <- xx_names[[1]]
df$car <- with(df, factor(car, levels=car, ordered=TRUE))
mdf <- reshape2::melt(df, id.vars="car")
p <- ggplot(mdf, aes(x = variable, y = car)) + geom_tile(aes(fill = value))

mat <- matrix(unlist(dplyr::select(df,-car)),nrow=nrow(df))
colnames(mat) <- colnames(df)[1:ncol(df)-1]
rownames(mat) <- rownames(df)

# hide axis ticks and grid lines
eaxis <- list(
  showticklabels = FALSE,
  showgrid = FALSE,
  zeroline = FALSE
)

p_empty <- plot_ly(filename="r-docs/dendrogram") %>%
  # note that margin applies to entire plot, so we can
  # add it here to make tick labels more readable
  layout(margin = list(l = 200),
         xaxis = eaxis,
         yaxis = eaxis)

subplot(px, p_empty, p, py, nrows = 2, margin = 0.01)

qui donne:

enter image description here

J'ai un peu changé le code afin que dans mon cas, la carte thermique soit générée avec plotly plutôt que ggplot car elle s'exécute plus rapidement sur mes vraies données volumineuses, donc je fais:

heatmap.plotly <- plot_ly() %>% add_heatmap(z=~mat,x=factor(colnames(mat),lev=colnames(mat)),y=factor(rownames(mat),lev=rownames(mat)))

Puis:

subplot(px, p_empty, heatmap.plotly, py, nrows = 2, margin = 0.01)

qui donne: enter image description here

Mes questions sont:

  1. Comment puis-je ne pas couper les étiquettes de ligne et de colonne de la carte thermique comme elles le font dans les deux tracés?

  2. L'étiquette du colorant est remplacée par "mat" sur la deuxième figure. Une idée de comment éviter ça?

  3. Comment modifier les marges entre la carte thermique et les dendrogrammes?

11
user1701545

Faire une carte thermique de cluster pleinement fonctionnelle avec complot n'est pas aussi simple qu'il y paraît au début. Heureusement, il existe un package R appelé heatmaply qui fait exactement cela. Vous pouvez voir de nombreux exemples de fonctionnalités dans la vignette en ligne .

Par exemple:

install.packages("ggplot2")
install.packages("plotly")
install.packages("heatmaply")

library(heatmaply)
heatmaply(scale(mtcars), k_row = 3, k_col = 2)

enter image description here

Cette figure est entièrement interactive (à la fois à partir de la carte thermique et du dendrogramme). Notez qu'il utilise dendextend (une version plus développée de ggdendro, qui peut également, par exemple, prendre en compte les couleurs de branche/type de ligne/largeur de ligne)

Plus précisément définition des marges des dendrogrammes est un problème ouvert (à partir d'aujourd'hui seulement), mais cela sera probablement résolu bientôt.

8
Tal Galili

Comment puis-je ne pas couper les étiquettes de ligne et de colonne de la carte thermique, comme elles le font dans les deux tracés?

Essayez de définir les margins après la génération du tracé

sply <- subplot(px, p_empty, heatmap.plotly, py, nrows = 2)
sply <- layout(sply,
               margin = list(l = 150,
                             r = 0,
                             b = 50,
                             t = 0
                            )
               )

L'étiquette du colorant est remplacée par "mat" sur la deuxième figure. Une idée de comment éviter ça?

Je ne sais pas comment l'empêcher, mais vous pouvez remplacer l'étiquette.

sply$x$data[[3]]$colorbar$title <- 'mat'

Comment modifier les marges entre la carte thermique et les dendrogrammes?

Vous pouvez spécifier le domain pour chaque axe de chaque sous-tracé. yaxis correspond à l'intrigue dans le coin supérieur gauche, yaxis2 à l'intrigue juste à côté, etc.

Augmenter la distance fonctionne mieux que la diminuer.

sply <- layout(sply,
               yaxis = list(domain=c(0.47, 1)),
               xaxis = list(domain=c(0, 0.5)),
               xaxis3 = list(domain=c(0, 0.5)),
               xaxis4 = list(domain=c(0.5, 1)),
               )

enter image description here

pl <- subplot(px, p_empty, p, py, nrows = 2)
heatmap.plotly <- plot_ly() %>% add_heatmap(z=~mat,x=factor(colnames(mat),lev=colnames(mat)),y=factor(rownames(mat),lev=rownames(mat)))
sply <- subplot(px, p_empty, heatmap.plotly, py, nrows = 2)
sply$x$data[[3]]$colorbar$title <- 'mat'
sply <- layout(sply,
               yaxis = list(domain=c(0.47, 1)),
               xaxis = list(domain=c(0, 0.5)),
               xaxis3 = list(domain=c(0, 0.5)),
               xaxis4 = list(domain=c(0.5, 1)),
               margin = list(l = 150,
                             r = 0,
                             b = 50,
                             t = 0
                             )


               )

sply
5