我想使用ggplot2包并排放置两个图,即执行par(mfrow=c(1,2))的等效操作。
例如,我想让下面两个图以相同的比例并排显示。
x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)
我需要把它们放到同一个数据帧里吗?
qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
我想使用ggplot2包并排放置两个图,即执行par(mfrow=c(1,2))的等效操作。
例如,我想让下面两个图以相同的比例并排显示。
x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)
我需要把它们放到同一个数据帧里吗?
qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
当前回答
更新:这个答案非常古老。gridExtra::grid.arrange()现在是推荐的方法。 我把这个留在这里,也许有用。
Stephen Turner在Getting Genetics Done博客上发布了arrange()函数(参见文章中的应用说明)
vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
dots <- list(...)
n <- length(dots)
if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
if(is.null(nrow)) { nrow = ceiling(n/ncol)}
if(is.null(ncol)) { ncol = ceiling(n/nrow)}
## NOTE see n2mfrow in grDevices for possible alternative
grid.newpage()
pushViewport(viewport(layout=grid.layout(nrow,ncol) ) )
ii.p <- 1
for(ii.row in seq(1, nrow)){
ii.table.row <- ii.row
if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
for(ii.col in seq(1, ncol)){
ii.table <- ii.p
if(ii.p > n) break
print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col))
ii.p <- ii.p + 1
}
}
}
其他回答
是的,我认为你需要适当地安排你的数据。一种方法是:
X <- data.frame(x=rep(x,2),
y=c(3*x+eps, 2*x+eps),
case=rep(c("first","second"), each=100))
qplot(x, y, data=X, facets = . ~ case) + geom_smooth()
我相信在plyr或重塑中有更好的技巧——我仍然没有真正跟上速度 哈德利设计的这些强大的软件包。
使用重塑包可以完成如下操作。
library(ggplot2)
wide <- data.frame(x = rnorm(100), eps = rnorm(100, 0, .2))
wide$first <- with(wide, 3 * x + eps)
wide$second <- with(wide, 2 * x + eps)
long <- melt(wide, id.vars = c("x", "eps"))
ggplot(long, aes(x = x, y = value)) + geom_smooth() + geom_point() + facet_grid(.~ variable)
基于网格的解决方案的一个缺点。他们的一个缺点是很难像大多数期刊要求的那样用字母(A, B等)来标记这些图。
我写了cowplot包来解决这个(和其他一些)问题,特别是函数plot_grid():
library(cowplot)
iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
geom_boxplot() + theme_bw()
iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
geom_density(alpha = 0.7) + theme_bw() +
theme(legend.position = c(0.8, 0.8))
plot_grid(iris1, iris2, labels = "AUTO")
plot_grid()返回的对象是另一个ggplot2对象,你可以像往常一样用ggsave()保存它:
p <- plot_grid(iris1, iris2, labels = "AUTO")
ggsave("plot.pdf", p)
或者,你可以使用cowplot函数save_plot(),它是ggsave()的一个薄包装,可以很容易地获得组合图的正确尺寸,例如:
p <- plot_grid(iris1, iris2, labels = "AUTO")
save_plot("plot.pdf", p, ncol = 2)
(ncol = 2参数告诉save_plot()有两个并排的图像,而save_plot()使保存的图像宽度增加一倍。)
有关如何在网格中安排图的更深入描述,请参阅此小插图。还有一个小插图解释如何用一个共享的传说来制作情节。
一个常见的混淆点是cowplot包更改了默认的ggplot2主题。这个包之所以这样做,是因为它最初是为内部实验室使用而编写的,我们从不使用默认主题。如果这导致问题,您可以使用以下三种方法之一来解决它们:
1. 为每个情节手动设置主题。我认为始终为每个情节指定一个特定的主题是一个很好的实践,就像我在上面的示例中对+ theme_bw()所做的那样。如果您指定了一个特定的主题,那么默认主题并不重要。
2. 将默认主题恢复为ggplot2默认。你可以用一行代码做到这一点:
theme_set(theme_gray())
3.调用cowplot函数而不附加包。你也可以不调用library(cowplot)或require(cowplot),而是通过前置cowplot::来调用cowplot函数。例如,上面使用ggplot2默认主题的示例将变成:
## Commented out, we don't call this
# library(cowplot)
iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
geom_boxplot()
iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
geom_density(alpha = 0.7) +
theme(legend.position = c(0.8, 0.8))
cowplot::plot_grid(iris1, iris2, labels = "AUTO")
更新:
从cowplot 1.0开始,默认的ggplot2主题不再更改。 从ggplot2 3.0.0开始,可以直接对图进行标记,参见这里的示例。
您可以使用温斯顿张的R食谱下面的多绘图函数
multiplot(plot1, plot2, cols=2)
multiplot <- function(..., plotlist=NULL, cols) {
require(grid)
# Make a list from the ... arguments and plotlist
plots <- c(list(...), plotlist)
numPlots = length(plots)
# Make the panel
plotCols = cols # Number of columns of plots
plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols
# Set up the page
grid.newpage()
pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
vplayout <- function(x, y)
viewport(layout.pos.row = x, layout.pos.col = y)
# Make each plot, in the correct location
for (i in 1:numPlots) {
curRow = ceiling(i/plotCols)
curCol = (i-1) %% plotCols + 1
print(plots[[i]], vp = vplayout(curRow, curCol ))
}
}
并排的任意ggplot(或网格上的n个plot)
gridExtra包中的grid.arrange()函数将组合多个图;这就是把两个放在一起的方法。
require(gridExtra)
plot1 <- qplot(1)
plot2 <- qplot(1)
grid.arrange(plot1, plot2, ncol=2)
当两个图不是基于相同的数据时,这很有用,例如,如果您想在不使用重塑()的情况下绘制不同的变量。
这将把输出作为副作用绘制出来。要将副作用打印到文件中,请指定一个设备驱动程序(如pdf、png等)。
pdf("foo.pdf")
grid.arrange(plot1, plot2)
dev.off()
或者,将arrangeGrob()与ggsave()结合使用,
ggsave("foo.pdf", arrangeGrob(plot1, plot2))
这相当于使用par(mfrow = c(1,2))绘制两个不同的图。这不仅节省了整理数据的时间,而且当你想要两个不同的图时,这是必要的。
附录:facet的使用
切面有助于为不同的群体制作相似的图。下面的许多回答都指出了这一点,但我想用与上面的图等效的例子来强调这种方法。
mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1))
qplot(data = mydata,
x = myX,
facets = ~myGroup)
ggplot(data = mydata) +
geom_bar(aes(myX)) +
facet_wrap(~myGroup)
更新
cowplot中的plot_grid函数值得作为grid.arrange的替代。参见下面@claus-wilke的回答和这个小插图,了解等效的方法;但该功能允许基于此小插图对地块位置和大小进行更精细的控制。