如何在ggplot2中一个在另一个上面排列热图和散点图

时间:2013-05-22 21:11:12

标签: r plot ggplot2 heatmap reshape

我是一个使用ggplot2的新手,我试图在热图上方绘制一个散点图。两个图都具有相同的离散x轴。

这是我正在尝试的代码:

library(ggplot2)
library(grid)
library(reshape2)
#data for the scatterplot

df = data.frame(id1 = letters[1:10], C = abs(rnorm(10)))

#scatter plot 
p1 <- ggplot(df, aes(x= id1, y = C)) + 
  geom_point(pch = 19) + theme_bw() + 
  scale_x_discrete(expand = c(0, 0), breaks = letters[1:10]) +
  theme(legend.position = "none") + theme(axis.title.y = element_blank()) + theme(axis.title.x = element_blank())

#data for the heatmap
X = data.frame(matrix(rnorm(100), nrow = 10))
names(X) = month.name[1:10]
X = melt(cbind(id1 = letters[1:10], X))

#heatmap 
p2 <- ggplot(X,
             aes(x = id1, y = variable, fill = value))
p2 <- p2 + geom_tile()
p2 <- p2 + scale_fill_gradientn(colours = c("blue", "white" , "red"))
p2 <- p2 + theme(legend.position = "none") + theme(axis.title.y = element_blank()) + theme(axis.title.x = element_blank())
p2 <- p2 + scale_x_discrete(expand = c(0, 0), breaks = letters[1:10])
p2 <- p2 + scale_y_discrete(expand = c(0, 0))

layt <- grid.layout(nrow=2,ncol=1,heights=c(2/8,6/8),default.units=c('null','null'))

vplayout <- function(x,y) {viewport(layout.pos.row = x, layout.pos.col = y)}

grid.newpage()
pushViewport(viewport(layout=layt))
print(p1,vp=vplayout(1,1))
print(p2,vp = vplayout(2,1))

问题在于轴不是一个位于另一个之上。

https://mail.google.com/mail/u/0/?ui=2&ik=81975edabc&view=att&th=13ece12a06a3cea2&attid=0.1&disp=emb&realattid=ii_13ece128398baede&zw&atsh=1

有什么解决方案吗?有可能重塑数据并制作像facet这样的东西吗?

2 个答案:

答案 0 :(得分:2)

另一种选择:

grid.draw(gtable:::rbind.gtable(ggplotGrob(p1),
                                ggplotGrob(p2), size='last'))

(理想情况下,人们会想要size=max,但它有一个阻止它工作的错误。)

答案 1 :(得分:1)

这里有一些技巧。首先,即使您具有相同的离散轴,刻度线也会得到不同的处理。当您执行expand = c(0,0)时,在散点图上,刻度线现在与y轴对齐,而在热图上,它位于类别的中心。我的解决方法是手动为散点图分配expand值,以便有一个1/2的分类值的间隙。因为有10个分类值,在这种情况下它是0.05(1/10)/2)。这些点现在将与每个类别的中心对齐。

问题的另一面是因为y标签的大小不同,它们会抛弃其余的对齐方式。解决方案来自this question,使用ggplot_gtable包中的grid.arrangegridExtra

library(gridExtra)
#data for the scatterplot

df = data.frame(id1 = letters[1:10], C = abs(rnorm(10)))

#scatter plot 
p1 <- ggplot(df, aes(x= id1, y = C)) + 
  geom_point(pch = 19) + theme_bw() + 
# Change the expand values
  scale_x_discrete(expand = c(0.05, 0.05), breaks = letters[1:10]) +
  #scale_y_discrete(breaks = NULL) +

  theme(legend.position = "none") + theme(axis.title.y = element_blank()) + theme(axis.title.x = element_blank())
p1
#data for the heatmap
X = data.frame(matrix(rnorm(100), nrow = 10))
names(X) = month.name[1:10]
X = melt(cbind(id1 = letters[1:10], X))

#heatmap 
p2 <- ggplot(X,
             aes(x = id1, y = variable, fill = value))
p2 <- p2 + geom_tile()
p2 <- p2 + scale_fill_gradientn(colours = c("blue", "white" , "red"))
p2 <- p2 + theme(legend.position = "none") + theme(axis.title.y = element_blank()) + theme(axis.title.x = element_blank())
p2 <- p2 + scale_x_discrete(expand = c(0, 0), breaks = letters[1:10])
p2 <- p2 + scale_y_discrete(expand = c(0, 0))

#Here's the gtable magic
gp1<- ggplot_gtable(ggplot_build(p1))
gp2<- ggplot_gtable(ggplot_build(p2))
#This identifies the maximum width
maxWidth = unit.pmax(gp1$widths[2:3], gp2$widths[2:3])
#Set each to the maximum width
gp1$widths[2:3] <- maxWidth
gp2$widths[2:3] <- maxWidth
#Put them together
grid.arrange(gp1, gp2)

编辑 - 请参阅@ baptiste的答案,了解更优雅的y轴对齐方法

enter image description here