2013-06-17 12 views
16

Ho due grafici che sto ponendo uno sopra l'altro, nel modo seguente:ggplot2 e gridExtra: rimuovere completamente la striscia in facet_grid - non solo invisibile

library(ggplot2) 
library(gridExtra) 
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() 
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() 
p2 <- p2 + facet_grid(cyl ~ .) 
grid.arrange(p1, p2, ncol=1) 

Per questo ho bisogno gli assi x di i grafici superiore e inferiore per allineare, tuttavia a causa della striscia a sinistra, il grafico sfaccettato è più stretto rispetto al grafico superiore. Posso rendere invisibile la striscia utilizzando:

theme(strip.text.y = element_blank()) 
theme(strip.background = element_blank()) 

Tuttavia, questo non elimina lo spazio occupato dalla striscia. Quindi, o ho bisogno di un modo per sbarazzarmi del tutto della striscia, o di avere un modo per dividere il mio grafico sfaccettato in grafici separati, eppure in qualche modo condividere la stessa etichetta dell'asse y su di essi. Nel mio grafico ho due pannelli sfaccettati che non sono molto alti, e non c'è abbastanza spazio per ciascuno di essi per avere un asse y di dimensioni decenti.

Qualche suggerimento?

+0

La mia soluzione (in lattice, dove sono più fluente) è aggiungere la striscia alla trama "semplice". –

risposta

8

La mia soluzione sarebbe quella di trovare la larghezza della striscia e quindi impostare i margini di entrambi i grafici su zero, ma ridurre quello senza la striscia leggermente più piccola (la larghezza della striscia) in modo che siano avere la stessa dimensione Per tentativi ed errori sembra che la striscia sia larga circa 0,5 righe (ma immagino che si possa capire a livello programmatico). Quindi basta assicurarsi che il margine trama giusta nella trama senza il testo striscia è di 0,5 linee maggiore di quello con la striscia invisibile:

# Add a line of width 0.5 on the left but set all other margins to zero 
p1 <- p1 + theme(plot.margin = unit(c(0,0.5,0,0) , units = "lines")) 
# Set all margins to zero, the strip will take up a phantom amount of invisible space 
p2 <- p2 + theme(strip.text.y = element_blank() , 
    strip.background = element_blank(), 
    plot.margin = unit(c(0,0,0,0) , units = "lines")) 

grid.arrange(p1, p2, ncol=1) 

Ovviamente è possibile regolare i margini come si desidera (ad esempio, aggiungere 1 a la prima posizione in ciascun vettore numerico in plot.margin per ottenere un bordo di una riga lungo la parte superiore di ciascun grafico), a condizione di mantenere 0,5 righe più margine nel bordo destro del secondo grafico, avranno lo stesso aspetto.

enter image description here

+0

Perfetto, grazie! –

+0

@ ClaireArmstrong siete i benvenuti! :-) –

1

Ecco un'altra soluzione utilizzando viewport e grid.layout. Creo 2 viewport con 2 layout differenti. Poi posiziono i grafici ggplot2 usando l'argomento vp.

library(grid) 
pushViewport(plotViewport(c(1,1,1,1),layout = grid.layout(2, 1))) 
print(p2, vp = viewport(layout.pos.row = 2, layout.pos.col = 1)) 
pushViewport(viewport(layout.pos.row=1, 
    layout = grid.layout(1, 2,widths = unit(c(1,1),c("null",'lines'))))) 
print(p1, vp = viewport(layout.pos.row = 1, layout.pos.col = 1)) 
upViewport(2)    

enter image description here

1

Si potrebbe anche fare in questo modo e mantenere i titoli della striscia, che sarebbe informazioni pertinenti:

library(ggplot2) 
library(gridExtra) 
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() + 
     xlab(NULL) 
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() + 
     facet_wrap(~ cyl, ncol = 1) 
grid.arrange(p1, p2, ncol=1) 
1

Un'altra soluzione utilizzando le funzioni dal pacchetto gtable. Allinea le trame ma mantiene il testo della striscia. Utilizza la funzione gtable per inserire una colonna a destra di p1 uguale alla larghezza del testo della striscia di p2.

library(ggplot2) 
library(gridExtra) 
library(gtable) 

p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() 
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() 
p2 <- p2 + facet_grid(cyl ~ .) 

g1 = ggplotGrob(p1) 
# gtable_show_layout(g1) # View the layout 
# g1$widths    # Get the widths of g1 

g2 = ggplotGrob(p2) 
# gtable_show_layout(g2) # View the layout 
# g2$widths    # Check the widths of g2 

# Add new column to the right of g1 equal in width the strip width of g2. 
# In g2, strip width is the 5th element the vector g2$widths 
g1 <- gtable_add_cols(g1, g2$widths[5]) 
grid.arrange(g1, g2, ncol=1) 

enter image description here

## But note that if the y-axis titles and/or labels take up different widths, 
# the two plots are not aligned 
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() + 
    theme(axis.title.y = element_text(angle = 0, size = 30)) 
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() 
p2 <- p2 + facet_grid(cyl ~ .) 

g1 = ggplotGrob(p1) 
g2 = ggplotGrob(p2) 

g1 <- gtable_add_cols(g1, g2$widths[5]) # New column added to the right 
grid.arrange(g1, g2, ncol=1)    # Plots are not aligned 

enter image description here

# Need to set widths to the maximums in the two plots, 
# i.e., set g2 widths to be the same as g1 widths 
g2$widths <- g1$widths 
grid.arrange(g1, g2, ncol=1)   # Plots are aligned 

enter image description here

EDIT: O come suggerito da Baptiste, utilizzare gtable s' rbind() funzione:

g1 = ggplotGrob(p1) 
g2 = ggplotGrob(p2) 

g1 <- gtable_add_cols(g1, g2$widths[5], 4) # New column added to the right 

library(grid) 
grid.draw(rbind(g1, g2, size = "first")) 
+0

invece di 'grid.arrange()', io raccomanderei 'grid.draw (rbind (g1, g2))'. Ma hai bisogno di una [versione dev di gtable] (https://github.com/baptiste/gtable) (e R-devel per ora), altrimenti rbind non riesce a confrontare le larghezze. – baptiste

Problemi correlati