我想使用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()
当前回答
并排的任意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的回答和这个小插图,了解等效的方法;但该功能允许基于此小插图对地块位置和大小进行更精细的控制。
其他回答
如果您希望使用循环绘制多个ggplot图(例如:使用循环在ggplot中创建具有不同y轴值的多个图),上述解决方案可能不太有效,这是分析未知(或大型)数据集的理想步骤(例如,当您希望绘制数据集中所有变量的计数时)。
下面的代码展示了如何使用上面提到的“multiplot()”来实现这一点,其源代码在这里:http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2):
plotAllCounts <- function (dt){
plots <- list();
for(i in 1:ncol(dt)) {
strX = names(dt)[i]
print(sprintf("%i: strX = %s", i, strX))
plots[[i]] <- ggplot(dt) + xlab(strX) +
geom_point(aes_string(strX),stat="count")
}
columnsToPlot <- floor(sqrt(ncol(dt)))
multiplot(plotlist = plots, cols = columnsToPlot)
}
现在运行函数-以获取在一页上使用ggplot打印的所有变量的Counts
dt = ggplot2::diamonds
plotAllCounts(dt)
需要注意的一点是: 在上面的代码中使用aes(get(strX)),而不是aes_string(strX)将不会绘制所需的图形,这是在处理ggplot时通常在循环中使用的。相反,它会多次绘制最后一个图形。我还没有弄清楚为什么-它可能必须做aes和aes_string在ggplot中被调用。
除此之外,希望你会发现这个函数有用。
使用补丁包,你可以简单地使用+运算符:
library(ggplot2)
library(patchwork)
p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
p1 + p2
其他操作符包括/,用于堆叠图,并排放置图,以及(),用于对元素进行分组。例如,你可以用(p1 | p2 | p3) /p来配置上面一行的3个地块和下面一行的一个地块。有关更多示例,请参阅包文档。
是的,我认为你需要适当地安排你的数据。一种方法是:
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或重塑中有更好的技巧——我仍然没有真正跟上速度 哈德利设计的这些强大的软件包。
您可以使用温斯顿张的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 ))
}
}
Ggplot2基于网格图形,网格图形提供了在页面上安排图形的不同系统。par(mfrow…)命令并没有直接的对等物,因为网格对象(称为grobs)不一定是立即绘制的,但在转换为图形输出之前,可以作为常规R对象存储和操作。这比现在绘制基础图形的模型具有更大的灵活性,但策略必然略有不同。
我编写grid.arrange()是为了提供一个尽可能接近par(mfrow)的简单接口。在其最简单的形式中,代码看起来像:
library(ggplot2)
x <- rnorm(100)
eps <- rnorm(100,0,.2)
p1 <- qplot(x,3*x+eps)
p2 <- qplot(x,2*x+eps)
library(gridExtra)
grid.arrange(p1, p2, ncol = 2)
在这个小插图中详细介绍了更多的选项。
一个常见的抱怨是,图不一定是对齐的,例如,当它们有不同大小的轴标签时,但这是通过设计:网格。Arrange没有尝试处理特殊情况下的ggplot2对象,并将它们与其他grobs(例如,晶格图)同等对待。它只是将抓取放在矩形布局中。
对于ggplot2对象的特殊情况,我编写了另一个函数ggarrange,该函数具有类似的接口,它尝试对齐绘图面板(包括分面图),并尝试尊重用户定义的纵横比。
library(egg)
ggarrange(p1, p2, ncol = 2)
这两个函数都与ggsave()兼容。对于不同选项的一般概述和一些历史背景,本小插图提供了额外的信息。