Pergunta

Eu gostaria de colocar lado duas parcelas a lado usando o ggplot2 pacote , ou seja, fazer o equivalente a par(mfrow=c(1,2)).

Por exemplo, eu gostaria de ter as duas parcelas seguintes mostram lado-a-lado com a mesma escala.

x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)

Eu preciso colocá-los no mesmo data.frame?

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
Foi útil?

Solução

Qualquer ggplots side-by-side (ou n parcelas em uma grade)

A função grid.arrange() no pacote gridExtra irá combinar múltiplos parcelas; isto é como você colocar dois lado a lado.

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

Isto é útil quando as duas parcelas não são baseados nos mesmos dados, por exemplo, se você deseja plotar variáveis ??diferentes sem usar remodelar ().

Isto irá traçar a saída como um efeito colateral. Para imprimir o efeito colateral para um arquivo, especifique um driver de dispositivo (como pdf, png, etc), por exemplo.

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

ou, o uso arrangeGrob() em combinação com ggsave(),

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

Este é o equivalente de fazer duas parcelas distintas usando par(mfrow = c(1,2)). Isso não só economiza tempo organizando os dados, é necessário quando você quer dois lotes diferentes.


Apêndice: Usando Facetas

As facetas são úteis para a tomada de parcelas semelhantes para diferentes grupos. Este é apontada abaixo em muitas respostas abaixo, mas quero destacar essa abordagem com exemplos equivalentes às parcelas acima.

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)

Atualização

a função plot_grid no cowplot vale a verificação como uma alternativa para grid.arrange. Veja a resposta por @ Claus-wilke abaixo e este vinheta para uma abordagem equivalente; mas a função permite que controles mais finos da localização e tamanho da parcela, com base em esta vinheta .

Outras dicas

Uma desvantagem das soluções baseadas em grid.arrange é que eles tornam difícil rotular as parcelas com letras (A, B, etc.), como a maioria dos periódicos exigem.

Eu escrevi o pacote cowplot para resolver este ( e algumas outras questões), especificamente a função 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")

enter descrição da imagem aqui

O objeto que plot_grid() retornos é outro objeto ggplot2, e você pode salvá-lo com ggsave() como de costume:

p <- plot_grid(iris1, iris2, labels = "AUTO")
ggsave("plot.pdf", p)

Como alternativa, você pode usar o save_plot() função cowplot, que é um wrapper fino ao redor ggsave() que torna mais fácil para obter as dimensões corretas para as parcelas combinadas, por exemplo:.

p <- plot_grid(iris1, iris2, labels = "AUTO")
save_plot("plot.pdf", p, ncol = 2)

(O argumento ncol = 2 diz save_plot() que existem duas parcelas de side-by-side, e save_plot() torna a imagem salva duas vezes mais larga.)

Para uma descrição mais detalhada de como organizar plots em uma grade veja esta vinheta. Há também uma vinheta explicando como fazer lotes com um lenda compartilhada.

Um ponto comum de confusão é que o pacote cowplot muda o tema ggplot2 padrão. O pacote comporta dessa maneira porque foi originalmente escrito para usos laboratoriais internos, e nunca usar o tema padrão. Se este problema causas, você pode usar uma das três abordagens para trabalhar em torno deles:

1. Definir o tema manualmente para cada lote. Eu acho que é uma boa prática para especificar sempre um tema específico para cada trama, assim como eu fiz com + theme_bw() no exemplo acima. Se você especificar um determinado tema, o tema padrão não importa.

2. Reverter a volta tema padrão para o padrão ggplot2 Você pode fazer isso com uma linha de código:.

theme_set(theme_gray())

3. Chamar funções cowplot sem anexar o pacote. Você também pode não chamar library(cowplot) ou require(cowplot) e em vez disso chamar funções cowplot, antecedendo cowplot::. Por exemplo, o exemplo acima usando o tema ggplot2 padrão seria:

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

enter descrição da imagem aqui

Atualizações:

  • Como de cowplot 1.0, o tema ggplot2 padrão não é mais alterado.
  • A partir de ggplot2 3.0.0, parcelas podem ser rotulados diretamente, ver por exemplo, aqui.

Você pode usar a seguinte função multiplot de R de Winston Chang livro de receitas

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

}

Sim, me parece que você precisa para organizar seus dados de forma adequada. Uma maneira seria esta:

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

Estou certo há melhores truques em plyr ou remodelar - Ainda não estou realmente até a velocidade em todos estes pacotes poderosos por Hadley.

Usando o pacote remodelar você pode fazer algo como isto.

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)

Update: Esta resposta é muito antiga. gridExtra::grid.arrange() agora é a abordagem recomendada. I deixar isso aqui no caso, pode ser útil.


Stephen Turner postou a função arrange() em Primeiros Genetics Feito do blog (ver post para instruções de aplicação)

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

ggplot2 é baseado em gráficos grade, que fornecem um sistema diferente para organizar parcelas em uma página. O comando par(mfrow...) não tem um equivalente direto, como objetos de grade (chamado grobs ) não estão necessariamente desenhadas imediatamente, mas podem ser armazenados e manipulados como objetos R regulares antes de ser convertido em uma saída gráfica. Isto permite uma maior flexibilidade do que o desenhar isso agora modelo de base de gráficos, mas a estratégia é necessariamente um pouco diferente.

Eu escrevi grid.arrange() para fornecer uma interface simples o mais próximo possível para par(mfrow). Na sua forma mais simples, o código ficaria assim:

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)

 enter descrição da imagem aqui

Mais opções estão detalhadas no esta vinheta .

Uma queixa comum é que as parcelas não são necessariamente alinhados por exemplo quando eles têm eixos etiquetas de tamanho diferente, mas isso é por design: grid.arrange faz nenhuma tentativa de objetos ggplot2 casos especiais, e trata-los igualmente para outros grobs (parcelas de rede, por exemplo). Ele simplesmente coloca grobs em um layout retangular.

Para o caso especial de objectos ggplot2, eu escreveu uma outra função, ggarrange, com uma interface semelhante, que as tentativas para painéis de alinhamento da trama (incluindo parcelas facetadas) e tentativas para respeitar as proporções quando definida pelo utilizador.

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

Ambas as funções são compatíveis com ggsave(). Para uma visão geral das diferentes opções, e alguns contexto histórico, este ofertas vinheta informações adicionais .

Há também multipanelfigure pacote que vale a pena mencionar. Veja também esta resposta .

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

Criado em 2018/07/06 pelo reprex pacote (v0.2.0.9000).

Usando 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

enter descrição da imagem aqui

As soluções acima pode não ser eficiente se você quiser traçar vários gráficos ggplot usando um loop (por exemplo, como pediu aqui: a criação de várias parcelas em ggplot com diferentes valores do eixo Y usando um circular), o qual é um passo desejado em analisar o desconhecido (ou grande) conjuntos de dados (por exemplo, quando você quer Counts enredo de todas as variáveis ??em um data-set).

O código a seguir mostra como fazer isso usando o acima mencionado 'multiplot ()', cuja origem está aqui: 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)
}

Agora, execute a função - para obter contagens para todas as variáveis ??impressos usando ggplot em uma página

dt = ggplot2::diamonds
plotAllCounts(dt)

Uma coisa a notar é que:
usando aes(get(strX)), o que você usaria normalmente em loops quando se trabalha com ggplot, no código acima, em vez de aes_string(strX) não vai chamar os lotes desejados. Em vez disso, ele irá traçar a última trama muitas vezes. Eu ainda não descobri por quê -. Ele pode ter que fazer o aes e aes_string são chamados ggplot

Caso contrário, espero que você vai encontrar a função útil.

O pacote cowplot dá-lhe uma boa maneira de fazer isso, de uma maneira que a publicação ternos.

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

enter descrição da imagem aqui

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top