ggplot2를 사용한 단계별 플롯


339

내가 사용 옆에 두 개의 플롯 측을 배치 할 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()

나는 당신이 격자로 이것을 할 수 있다고 생각합니다. ggplot2는 어려운 요구 사항입니까?
JD Long

8
아니요. 그러나 이미 qplots를 조정할 때 이미 내가 좋아했던 방식으로 조정했습니다. :-) 그리고 ggplot으로 놀려고합니다.
Christopher DuBois


1
멋진 개요를 위해 네트를 참조 계란 패키지 : 한 페이지에 여러 플롯을 레이아웃
헨릭

답변:


505

모든 ggplot이 나란히 (또는 그리드의 n 플롯)

기능 grid.arrange()gridExtra패키지는 여러 플롯을 결합 할 것이다; 이것이 당신이 나란히 놓는 방법입니다.

require(gridExtra)
plot1 <- qplot(1)
plot2 <- qplot(1)
grid.arrange(plot1, plot2, ncol=2)

예를 들어 reshape ()을 사용하지 않고 다른 변수를 플롯하려는 경우 두 플롯이 동일한 데이터를 기반으로하지 않을 때 유용합니다.

결과를 부작용으로 플로팅합니다. 파일에 부작용을 인쇄하려면, (같은 디바이스 드라이버를 지정 pdf, png등등), 예를 들어

pdf("foo.pdf")
grid.arrange(plot1, plot2)
dev.off()

또는 사용 arrangeGrob()과 함께 ggsave(),

ggsave("foo.pdf", arrangeGrob(plot1, plot2))

이것은를 사용하여 두 개의 별개의 플롯을 만드는 것과 같습니다 par(mfrow = c(1,2)). 이것은 데이터 정렬 시간을 절약 할뿐만 아니라 두 개의 다른 플롯을 원할 때 필요합니다.


부록 : 패싯 사용

패싯은 여러 그룹에 대해 유사한 플롯을 만드는 데 도움이됩니다. 이것은 아래 많은 답변에서 아래에 지적되어 있지만 위의 플롯과 동등한 예제 로이 접근법을 강조하고 싶습니다.

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함수는의 cowplot대안으로 체크 아웃 할 가치가 grid.arrange있습니다. 동등한 접근 방법은 아래 @ claus-wilke 의 답변 과이 비 네트 를 참조하십시오 . 그러나이 비 네트를 기준으로 플롯 위치 및 크기를 미세하게 제어 할 수 있습니다 .


2
ggplot 객체를 사용하여 코드를 실행하면 sidebysideplot이 null입니다. 출력을 파일로 저장하려면 gridArrange를 사용하십시오. 참조 stackoverflow.com/questions/17059099/...

@Jim은 그것을 지적 해 주셔서 감사합니다. 내 답변을 수정했습니다. 질문이 남아 있으면 알려주세요.
David LeBauer

1
grid.aarange가 현재 지원 중단됩니까?
Atticus29

?grid.arrange이 기능을 이제는 sortGrob라고합니다. 나는 내가 a <- arrangeGrob(p1, p2)하고 나서 원하는 것을 할 수있었습니다 print(a).
blakeoft

@blakeoft 예제를 보았습니까? grid.arrange여전히 유효하고 사용되지 않는 기능입니다. 이 기능을 사용하려고 했습니까? 예상하지 못한 경우 어떻게됩니까?
David LeBauer 14 년

159

기반 솔루션의 단점 중 하나 grid.arrange는 대부분의 저널에서 요구하는대로 문자 (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 기능을 호출하십시오. 또한 앞에 추가하여 cowplot 함수를 호출 library(cowplot)하거나 require(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부터 플롯에 직접 레이블을 지정할 수 있습니다 (예 : 여기 참조) .

출력 cowplot에서 두 플롯 중 배경 테마를 제거하고 있습니까? 대안이 있습니까?
VAR121

@ VAR121 예, 한 줄의 코드입니다. 소개 비 네트의 첫 번째 섹션 끝에서 설명 : cran.rstudio.com/web/packages/cowplot/vignettes/…
Claus Wilke

이 패키지의 모든 플롯에 대해 동일한 y 스케일을 가질 수 있습니까?
Herman Toothrot

y 스케일을 수동으로 설정하여 일치시켜야합니다. 아니면 패싯을 고려하십시오.
Claus Wilke

grid.arrange ()를 사용하기 전에 각 플롯에 대해 ggtitle ()을 설정할 수 있습니까?
Seanosapien

49

Winston Chang의 R 요리 책multiplot 에서 다음 기능을 사용할 수 있습니다

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 ))
    }

}

24

패치 워크 패키지를 사용하면 간단히 +연산자 를 사용할 수 있습니다.

library(ggplot2)
library(patchwork)

p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))


p1 + p2

덧붙여 대는 세공


완벽을 기하기 위해 패치 워크도 이제 CRAN에 있습니다. 내 작은 편집에 만족
하시길 바랍니다

18

예, 데이터를 적절하게 정리해야합니다. 한 가지 방법은 다음과 같습니다.

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 또는 reshape에 더 나은 트릭이 있다고 확신합니다-Hadley의 강력한 패키지를 모두 빠르게 처리 할 수는 없습니다.


16

모양 변경 패키지를 사용하면 이와 같은 작업을 수행 할 수 있습니다.

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)

12

언급 할 가치가있는 다중 패널 셀프 패키지 도 있습니다 . 이 답변 도 참조하십시오 .

library(ggplot2)
theme_set(theme_bw())

q1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
q2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
q3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
q4 <- ggplot(mtcars) + geom_bar(aes(carb))

library(magrittr)
library(multipanelfigure)
figure1 <- multi_panel_figure(columns = 2, rows = 2, panel_label_type = "none")
# show the layout
figure1

figure1 %<>%
  fill_panel(q1, column = 1, row = 1) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2, row = 2)
figure1

# complex layout
figure2 <- multi_panel_figure(columns = 3, rows = 3, panel_label_type = "upper-roman")
figure2

figure2 %<>%
  fill_panel(q1, column = 1:2, row = 1) %<>%
  fill_panel(q2, column = 3, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2:3, row = 2:3)
figure2

2018-07-06에 reprex 패키지 (v0.2.0.9000)로 작성되었습니다.


9

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)

여기에 이미지 설명을 입력하십시오

이 비네팅 에는 더 많은 옵션이 자세히 설명되어 있습니다 .

하나의 일반적인 불만은 플롯이 서로 다른 크기의 축 레이블을 가질 때 반드시 정렬 될 필요는 없지만 이것은 의도적으로 설계된 것입니다. grid.arrangeggplot2 객체를 특수한 경우를 시도하지 않고 다른 grobs와 동일하게 취급합니다 (예 : 격자 플롯). ). 그 로브는 직사각형 레이아웃으로 배치됩니다.

ggplot2 객체의 특별한 경우에 ggarrange대해 비슷한 인터페이스를 가진 다른 함수를 작성했습니다.이 인터페이스는 플롯 패널 (면 처리 된 플롯 포함)을 정렬하려고 시도하고 사용자가 정의 할 때 종횡비를 존중하려고합니다.

library(egg)
ggarrange(p1, p2, ncol = 2)

두 기능 모두와 호환됩니다 ggsave(). 다양한 옵션과 역사적 배경에 대한 일반적인 개요를 위해이 비네팅은 추가 정보를 제공합니다 .


9

업데이트 : 이 답변은 매우 오래되었습니다. 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
  }
 }
}

9
그것은 기본적 매우 오래된 버전입니다 grid.arrange- 당신이 내게 물어 경우 패키지 버전이 더 나은 선택이다 (필자는 시간에 메일 링리스트에 게시하지 않았다 소원이 온라인 리소스를 업데이트하는 방법이 없습니다)
밥 티스트

4

사용 tidyverse:

x <- rnorm(100)
eps <- rnorm(100,0,.2)
df <- data.frame(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

여기에 이미지 설명을 입력하십시오


1

루프를 사용하여 여러 ggplot 플롯을 플로팅하려는 경우 위의 솔루션이 효율적이지 않을 수 있습니다 (예 : 루프를 사용하여 다른 Y 축 값으로 ggplot에서 여러 플롯 생성 ). 또는 큰) 데이터 세트 (예 : 데이터 세트에있는 모든 변수의 개수를 플로팅하려는 경우).

아래 코드는 위에서 언급 한 '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을 사용하여 인쇄 된 모든 변수의 개수를 가져옵니다.

dt = ggplot2::diamonds
plotAllCounts(dt)

주목 해야 할 것은 위의 코드에서 대신 작업 할 때 일반적으로 루프에서 사용하는
using을 사용 하면 원하는 플롯이 그려지지 않습니다. 대신 마지막 플롯을 여러 번 플롯합니다. 그것은 할 수있다 - 나는 이유를 생각하지 않은 및 호출됩니다 .aes(get(strX))ggplotaes_string(strX)aesaes_stringggplot

그렇지 않으면이 기능이 유용하기를 바랍니다.


1
코드는 비효율적이며에서 권장되지 않는 plots개체 for-loop를 확장 R합니다. 그것을 할 수있는 더 나은 방법 찾아이 큰 게시물을 참조하십시오 : R의 효율적인 축적 , 데이터 프레임의 행에 걸쳐 기능을 적용tidyverse와 R의 워크 플로우를 행을 지향

변수를 반복하는보다 효율적인 방법은 stackoverflow.com/a/52045613/786542tidy evaluationggplot2 v.3.0.0
Tung

0

내 경험상 gridExtra : grid.arrange는 루프에서 플롯을 생성하려고하면 완벽하게 작동합니다.

짧은 코드 스 니펫 :

gridExtra::grid.arrange(plot1, plot2, ncol = 2)

4:20의 12 월 2 일 17 일에 대한 침례 자의 답변에 대한 답은 어떻게 향상됩니까? 답변이 중복 된 것 같습니다. 여기에 수용 가능한 답변을 확인하십시오. 답변 방법
Peter

루프 내에서 필요에 따라 플롯을 나눌 수 없으므로 제안입니다. 처음에는 구현과 함께 내 for 루프의 전체 스 니펫을 작성했지만 당분간 그것에 대해 결정했습니다. 일주일 정도에 전체 코드를 업데이트합니다.
Mayank Agrawal

처음에는 cowplot 패키지를 사용하여 시도했지만 실패했습니다. 내 빠른 스캔에서 아무도 for 루프 내에서 다중 플로팅 솔루션을 언급하지 않았으므로 내 의견은 없습니다. 내가 틀렸다면 의견을 보내주십시오.
Mayank Agrawal

답변의 코드에 for 루프가 포함 된 경우 다른 루프가 있습니다.
피터

나는 일주일에 여기에서 업데이트하고 Kaggle의 전체 프로젝트를 업데이트 할 것입니다. 건배.
Mayank Agrawal

-3

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")

여기에 이미지 설명을 입력하십시오


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.