我是一个使用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))
问题在于轴不是一个位于另一个之上。
有什么解决方案吗?有可能重塑数据并制作像facet这样的东西吗?
答案 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.arrange
和gridExtra
。
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
轴对齐方法