2012-02-28 1 views
23

Я думал об использовании функций par() или layout() для объединения ggplots. Можно ли использовать эти функции?Комбинированный график ggplot2 (Не в одном графике), используя функцию par() или layout()?

Скажите, что я хочу построить ggplot для диаграммы рассеяния и ggplot для гистограммы. И я хочу объединить два участка (НЕ В ОДНОМ УЧАСТКЕ). Это применимо?

Я попробовал это с простым построением графика в R, не используя функции ggplot. И это работает на самом деле.

Вот пример из Quick-R, Link: http://www.statmethods.net/advgraphs/layout.html

# 4 figures arranged in 2 rows and 2 columns 
attach(mtcars) 
par(mfrow=c(2,2)) 
plot(wt,mpg, main="Scatterplot of wt vs. mpg") 
plot(wt,disp, main="Scatterplot of wt vs disp") 
hist(wt, main="Histogram of wt") 
boxplot(wt, main="Boxplot of wt") 

# One figure in row 1 and two figures in row 2 
attach(mtcars) 
layout(matrix(c(1,1,2,3), 2, 2, byrow = TRUE)) 
hist(wt) 
hist(mpg) 
hist(disp) 

Но когда я пытаюсь использовать ggplot, и объединить сюжет, я не получаю выход.

+0

ggplot2 является а не базовую графику, поэтому вы не можете объединить ggplot2 и макет или пар (mfrow). вам нужно использовать, например, plot.arrange и т. д. в gridExtra. Или вы можете играть с видовым экраном в сетке. – kohske

+0

Поскольку вы просили что-то вроде 'layout()', вы, вероятно, хотите что-то вроде 'grid.arrange()' (как упоминалось в кохске). [Этот связанный пост] (http://stackoverflow.com/questions/7993722/creating-arbitrary-panes-in-ggplot2/7996205#7996205) (и в частности ответ Бен-Болкера) даст вам хорошую отправную точку. –

ответ

32
library(ggplot2) 
library(grid) 


vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y) 


plot1 <- qplot(mtcars,x=wt,y=mpg,geom="point",main="Scatterplot of wt vs. mpg") 
plot2 <- qplot(mtcars,x=wt,y=disp,geom="point",main="Scatterplot of wt vs disp") 
plot3 <- qplot(wt,data=mtcars) 
plot4 <- qplot(wt,mpg,data=mtcars,geom="boxplot") 
plot5 <- qplot(wt,data=mtcars) 
plot6 <- qplot(mpg,data=mtcars) 
plot7 <- qplot(disp,data=mtcars) 

# 4 figures arranged in 2 rows and 2 columns 
grid.newpage() 
pushViewport(viewport(layout = grid.layout(2, 2))) 
print(plot1, vp = vplayout(1, 1)) 
print(plot2, vp = vplayout(1, 2)) 
print(plot3, vp = vplayout(2, 1)) 
print(plot4, vp = vplayout(2, 2)) 


# One figure in row 1 and two figures in row 2 
grid.newpage() 
pushViewport(viewport(layout = grid.layout(2, 2))) 
print(plot5, vp = vplayout(1, 1:2)) 
print(plot6, vp = vplayout(2, 1)) 
print(plot7, vp = vplayout(2, 2)) 
+0

Спасибо вам всем, ребята, моя проблема решена. –

+1

To Maiasaura, Благодарим вас за сценарий/код. Но у меня возникла ошибка, когда я печатаю plot1 и plot2, в котором говорится: «Ошибка в eval (expr, envir, enc): объект« wt »не найден». Однако, я исправил его, переставив аргумент в plot1 и plot2. plot1 <- qplot (x = wt, y = mpg, data = mtcars, geom = "point", main = "Scatterplot of wt vs. mpg") и plot2 <- qplot (x = wt, y = disp , data = mtcars, geom = "point", main = "Scatterplot of wt vs disp") Еще раз спасибо за быстрый ответ. –

+0

@Maiasaura Спасибо за отличные ответы. Как добавить заголовок для всей сетки в качестве основного заголовка. Я видел параметр grid.text, но в сетке 2 на 4 он не выглядит красиво в верхней и средней частях. –

7

Ответ с участием grid.layout работы, я использовал его, и я до проголосовал его. Тем не менее, я обычно считаю, что это решение слишком утомительно и подвержено ошибкам, и я подозреваю, что большинство энтузиастов ggplot2, которые это делают, регулярно завершают эту функцию. В предыдущих поисках я нашел несколько таких функций обертки, но мое текущее решение рабочей лошадки находится в grid addon package called gridExtra. Он имеет полезные аргументы, но настроить по умолчанию строк/столбцов часто то, что вы хотели в первую очередь:

library("ggplot2") 
# Generate list of arbitrary ggplots 
plot1 <- qplot(data = mtcars, x=wt, y=mpg, geom="point",main="Scatterplot of wt vs. mpg") 
plot2 <- qplot(data = mtcars, x=wt, y=disp, geom="point",main="Scatterplot of wt vs disp") 
plot3 <- qplot(wt,data=mtcars) 
plot4 <- qplot(wt,mpg,data=mtcars,geom="boxplot") 
plot5 <- qplot(wt,data=mtcars) 
plot6 <- qplot(mpg,data=mtcars) 
plot7 <- qplot(disp,data=mtcars) 
# You might have produced myPlotList using instead lapply, mc.lapply, plyr::dlply, etc 
myPlotList = list(plot1, plot2, plot3, plot4, plot5, plot6, plot7) 
library("gridExtra") 
do.call(grid.arrange, myPlotList) 

Обратите внимание, как фактическое «объединить свои участки в один графический» код был одной строки (после загрузки gridExtra) , Можно возразить, что сдачи участков в список была дополнительная строка, но на самом деле я мог бы альтернативно использоваться

grid.arrange(plot1, plot2, plot3, plot4, plot5, plot6, plot7) 

Для небольшого числа ggplots это может быть предпочтительным. Однако для n_plots > 4 вы начнете возмущаться, чтобы назвать и набрать их все.

+0

, если вам нужны два столбца, например, в результате grid.arrange, что бы содержала последняя строка? Я пробовал варианты на args = list (ncol = 2) – lawyeR

+4

Вот один-лайнер: 'do.call (grid.arrange, c (myPlotList, list (ncol = 2)))' –

12

Утилита, я думаю, заслуживает большего внимания, так как это layOut, прежде чем пакет wq (обратите внимание на столицу «O»). С тех пор он был удален из пакета wq, поэтому я поставил код ниже и переименовал его lay_out, чтобы соответствовать типичному стилю ggplot. Это похоже на base::layout тем, что графики могут быть разного размера, выложены рядами и колоннами. Каждый аргумент lay_out представляет собой 3-элементный список, состоящий из графика, индексов строк для его построения и индексов столбцов для его построения.

Например, используя участки @Paul McMurdie, в

lay_out(list(plot1, 1, 1), 
     list(plot2, 1, 2), 
     list(plot3, 2, 1), 
     list(plot4, 2, 2), 
     list(plot5, 3, 1:2), 
     list(plot6, 4, 1:2), 
     list(plot7, 1:2, 3)) 

enter image description here

lay_out = function(...) {  
    x <- list(...) 
    n <- max(sapply(x, function(x) max(x[[2]]))) 
    p <- max(sapply(x, function(x) max(x[[3]]))) 
    grid::pushViewport(grid::viewport(layout = grid::grid.layout(n, p)))  

    for (i in seq_len(length(x))) { 
     print(x[[i]][[1]], vp = grid::viewport(layout.pos.row = x[[i]][[2]], 
      layout.pos.col = x[[i]][[3]])) 
    } 
} 

(код получен от предыдущей версии wq пакета, от commit history on the unofficial Github CRAN mirror.)

+0

Мне очень нравятся эти решения. grid.arrange не предлагает хорошее размещение участков. – ahs85

+0

@Grego. Пакет wq (качество воды), похоже, не имеет функции layOut(). Это верно? – lawyeR

+1

@lawyeR, очевидно, так. Я добавил код к моему ответу. – Gregor