与ggplot2并排绘图
我想使用ggplot2软件包并排放置两个图,即做相当于par(mfrow=c(1,2))
。
例如,我希望以下两个地块以相同的比例并排显示。
x <- rnorm(100) eps <- rnorm(100,0,.2) qplot(x,3*x+eps) qplot(x,2*x+eps)
我需要把它们放在相同的data.frame?
qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
任何ggplots并排(或n个网格)
gridExtra
包中的函数grid.arrange()
将组合多个图; 这是你如何把两个并排。
require(gridExtra) plot1 <- qplot(1) plot2 <- qplot(1) grid.arrange(plot1, plot2, ncol=2)
如果两个图不基于相同的数据,例如如果要在不使用reshape()的情况下绘制不同的variables,这是非常有用的。
这将把输出作为副作用。 要将副作用打印到文件,请指定设备驱动程序(如pdf
, png
等),例如
pdf("foo.pdf") grid.arrange(plot1, plot2) dev.off()
或者,与ggsave()
结合使用ggsave()
,
ggsave("foo.pdf", arrangeGrob(plot1, plot2))
这相当于使用par(mfrow = c(1,2))
创build两个不同的地块。 这不仅节省了安排数据的时间,而且当你需要两个不相似的地块时也是必要的。
附录:使用分面
方面有助于为不同的团体制作类似的情节。 下面的许多答案都指出了这一点,但我想用相当于上述图表的例子来强调这种方法。
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)
更新
作为plot_grid
的替代scheme, grid.arrange
的plot_grid
函数值得检查。 请参阅下面的@ claus-wilke和这个小插曲的回答,以获取相同的方法。 但是该function可以根据这个小插图对绘图位置和大小进行更精细的控制。
我从来没有喜欢基于grid.arrange
的解决scheme,因为它们使得很难用字母(A,B等)来标注这些地块,正如大多数期刊所要求的那样。 用grid.arrange
alignment图也很困难。
我写了cowplot包来解决这些问题,特别是函数plot_grid()
:
require(cowplot) plot1 <- qplot(1) plot2 <- qplot(1) plot_grid(plot1, plot2, align='h', labels=c('A', 'B'))
有关plot_grid()
的更深入的描述,请参阅此小插图。
您可以使用Winston Chang的R食谱中的以下多function函数
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 )) } }
是的,你需要适当地安排你的数据。 一种方法是这样的:
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()
我相信有更好的技巧或重塑 – 我仍然不是真的要加快哈德利所有这些强大的包裹。
使用重塑包你可以做这样的事情。
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)
Stephen Turner 在Getting Genetics Done博客上发布了arrange()
函数 (请参阅post了解应用程序说明); 但是build议使用grid.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 } } }
上面的解决scheme可能不是有效的,如果你想绘制多个ggplot图使用循环(例如,这里问: 在ggplot中创build多个图与不同的Y轴值使用循环 ),这是分析未知的期望的步骤或大的)数据集(例如,当你想绘制一个数据集中的所有variables的计数)。
下面的代码显示了如何使用上面提到的“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打印的所有variables的Counts
dt = ggplot2::diamonds plotAllCounts(dt)
有一点要注意的是:
使用aes(get(strX))
,在使用ggplot
,通常在循环中使用aes(get(strX))
,而在上面的代码中不使用aes_string(strX)
将不绘制所需的图。 相反,它会多次绘制最后的情节。 我还没有想出为什么 – 它可能必须做的aes
和aes_string
在ggplot
中调用。
否则,希望你能find有用的function。
使用dplyr
和tidyr
:
x <- rnorm(100) eps <- rnorm(100,0,.2) df <- as.data.frame(cbind(x, eps)) %>% mutate(p1 = 3*x+eps, p2 = 2*x+eps) %>% tidyr::gather("plot", "value", 3:4) %>% ggplot(aes(x = x , y = value))+ geom_point()+geom_smooth()+facet_wrap(~plot, ncol =2) df
cowplot
你一个很好的方式来做到这一点,适合出版。
x <- rnorm(100) eps <- rnorm(100,0,.2) A = qplot(x,3*x+eps, geom = c("point", "smooth"))+theme_gray() B = qplot(x,2*x+eps, geom = c("point", "smooth"))+theme_gray() cowplot::plot_grid(A, B, labels = c("A", "B"), align = "v")