一种(不幸的是不太懒惰的)方法是将图例作为单独的 grobs(图形对象)提取,然后分别布置图形和图例。这样可以更好地控制每个对象分配了多少空间。幸运的是,有几个辅助函数使这个过程相对轻松。以下是一个示例:
library(gridExtra)
p1 = qplot(data = d[d$variable != "very_long_label_name",], factor(value),
position = "dodge", geom = "histogram", fill = variable)
p2 = qplot(data = d[d$variable != "y",], factor(value), position = "dodge",
geom = "histogram", fill = variable)
我们需要几个辅助函数,一个是用于提取图例的,另一个是用于调整图例图形大小使它们对齐的函数:
get_leg = function(a.gplot){
tmp <- ggplot_gtable(ggplot_build(a.gplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
legend
}
justify <- function(x, hjust="center", vjust="center", draw=TRUE){
w <- sum(x$widths)
h <- sum(x$heights)
xj <- switch(hjust,
center = 0.5,
left = 0.5*w,
right=unit(1,"npc") - 0.5*w)
yj <- switch(vjust,
center = 0.5,
bottom = 0.5*h,
top=unit(1,"npc") - 0.5*h)
x$vp <- viewport(x=xj, y=yj)
if(draw) grid.draw(x)
return(x)
}
现在提取图例并布置图表:
leg1 = get_leg(p1)
leg2 = get_leg(p2)
w = c(0.6,0.4)
png("test1.png", height = 3, width = 6, units="in", res=100)
grid.arrange(p1 + theme(legend.position="none"),
justify(leg1,"left","center"),
widths=w, ncol=2)
dev.off()
png("test2.png", height = 3, width = 6, units="in", res=100)
grid.arrange(p2 + theme(legend.position="none"),
justify(leg2,"left","center"),
widths=w, ncol=2)
dev.off()
如果您的绘图中y轴的值不同,可能会出现绘图区域不垂直对齐的情况,这是由于当y值具有更多字符时,更多的宽度被分配给y轴标签(而不是绘图区域)。因此,您还需要使绘图区域的宽度相等,以使绘图区域在垂直方向上对齐。以下是一个示例:
p3 = ggplot(iris, aes(Sepal.Length, Sepal.Width*1e6, colour=Species)) +
geom_point()
leg3 = get_leg(p3)
gA <- ggplotGrob(p1 + theme(legend.position="none"))
gB <- ggplotGrob(p3 + theme(legend.position="none"))
maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
gA$widths[2:5] <- as.list(maxWidth)
gB$widths[2:5] <- as.list(maxWidth)
png("test1a.png", height = 3, width = 6, units="in", res=100)
grid.arrange(gA, justify(leg1,"left","center"),
widths=w, ncol=2)
dev.off()
png("test3.png", height = 3, width = 6, units="in", res=100)
grid.arrange(gB, justify(leg3,"left","center"),
widths=w, ncol=2)
dev.off()
现在这里是原始的p1,接下来是调整宽度后的p1和p3版本: