У меня есть heatmap
(выражение гена из набора образцов):
set.seed(10)
mat <- matrix(rnorm(24*10,mean=1,sd=2),nrow=24,ncol=10,dimnames=list(paste("g",1:24,sep=""),paste("sample",1:10,sep="")))
dend <- as.dendrogram(hclust(dist(mat)))
row.ord <- order.dendrogram(dend)
mat <- matrix(mat[row.ord,],nrow=24,ncol=10,dimnames=list(rownames(mat)[row.ord],colnames(mat)))
mat.df <- reshape2::melt(mat,value.name="expr",varnames=c("gene","sample"))
require(ggplot2)
map1.plot <- ggplot(mat.df,aes(x=sample,y=gene))+geom_tile(aes(fill=expr))+scale_fill_gradient2("expr",high="darkred",low="darkblue")+scale_y_discrete(position="right")+
theme_bw()+theme(plot.margin=unit(c(1,1,1,-1),"cm"),legend.key=element_blank(),legend.position="right",axis.text.y=element_blank(),axis.ticks.y=element_blank(),panel.border=element_blank(),strip.background=element_blank(),axis.text.x=element_text(angle=45,hjust=1,vjust=1),legend.text=element_text(size=5),legend.title=element_text(size=8),legend.key.size=unit(0.4,"cm"))
(Левая сторона обрезается из-за аргументов plot.margin
, которые я использую, но мне нужно это для показанного ниже).
Затем я prune
строка dendrogram
в соответствии с значением отсечки глубины, чтобы получить меньшее количество кластеров (т.е. только глубокие расщепления), и сделайте некоторое редактирование в полученном dendrogram
, чтобы оно было построено так, как я хочу
depth.cutoff <- 11
dend <- cut(dend,h=depth.cutoff)$upper
require(dendextend)
gg.dend <- as.ggdend(dend)
leaf.heights <- dplyr::filter(gg.dend$nodes,!is.na(leaf))$height
leaf.seqments.idx <- which(gg.dend$segments$yend %in% leaf.heights)
gg.dend$segments$yend[leaf.seqments.idx] <- max(gg.dend$segments$yend[leaf.seqments.idx])
gg.dend$segments$col[leaf.seqments.idx] <- "black"
gg.dend$labels$label <- 1:nrow(gg.dend$labels)
gg.dend$labels$y <- max(gg.dend$segments$yend[leaf.seqments.idx])
gg.dend$labels$x <- gg.dend$segments$x[leaf.seqments.idx]
gg.dend$labels$col <- "black"
dend1.plot <- ggplot(gg.dend,labels=F)+scale_y_reverse()+coord_flip()+theme(plot.margin=unit(c(1,-3,1,1),"cm"))+annotate("text",size=5,hjust=0,x=gg.dend$label$x,y=gg.dend$label$y,label=gg.dend$label$label,colour=gg.dend$label$col)
И я рисую их вместе, используя cowplot
plot_grid
:
require(cowplot)
plot_grid(dend1.plot,map1.plot,align='h',rel_widths=c(0.5,1))
Хотя работает align='h'
, он не идеален.
Нанесение обрезки dendrogram
на map1.plot
с помощью plot_grid
иллюстрирует это:
dend0.plot <- ggplot(as.ggdend(dend))+scale_y_reverse()+coord_flip()+theme(plot.margin=unit(c(1,-1,1,1),"cm"))
plot_grid(dend0.plot,map1.plot,align='h',rel_widths=c(1,1))
Отверстия сверху и снизу dendrogram
кажутся сплющенными к центру. Воспроизведение с помощью scale
похоже на способ его настройки, но значения шкалы, похоже, зависят от фигуры, поэтому мне интересно, есть ли способ сделать это более принципиально.
Далее, я делаю анализ терминов по обогащению для каждого кластера моего heatmap
. Предположим, что этот анализ дал мне этот data.frame
:
enrichment.df <- data.frame(term=rep(paste("t",1:10,sep=""),nrow(gg.dend$labels)),
cluster=c(sapply(1:nrow(gg.dend$labels),function(i) rep(i,5))),
score=rgamma(10*nrow(gg.dend$labels),0.2,0.7),
stringsAsFactors = F)
Что бы я хотел сделать, это нарисовать этот data.frame
как heatmap
и поместить над ним подрез dendrogram
(аналогично тому, как он помещен слева от выражения heatmap
).
Итак, я попробовал plot_grid
снова подумать, что align='v'
будет работать здесь:
Сначала регенерируйте график дендрограммы, располагая его вверх:
dend2.plot <- ggplot(gg.dend,labels=F)+scale_y_reverse()+theme(plot.margin=unit(c(-3,1,1,1),"cm"))
Теперь, пытаясь построить их вместе:
plot_grid(map2.plot,dend2.plot,align='v')
plot_grid
, похоже, не может выровнять их, как показывает рисунок, и предупреждающее сообщение, которое оно выбрасывает:
In align_plots(plotlist = plots, align = align) :
Graphs cannot be vertically aligned. Placing graphs unaligned.
Похоже, что это близко:
plot_grid(map2.plot,dend2.plot,rel_heights=c(1,0.5),nrow=2,ncol=1,scale=c(1,0.675))
Это достигается после игры с параметром scale
, хотя сюжет выходит слишком широко. Так что, опять же, мне интересно, есть ли способ обойти это или как-то предопределить, что является правильным scale
для любого заданного списка dendrogram
и heatmap
, возможно, по их размерам.