Rata kiri dua tepi grafik (ggplot)

105

Saya menggunakan ggplot dan memiliki dua grafik yang ingin saya tampilkan di atas satu sama lain. Saya menggunakan grid.arrangedari gridExtra untuk menumpuknya. Masalahnya adalah saya ingin tepi kiri grafik sejajar serta tepi kanan terlepas dari label sumbu. (masalah muncul karena label dari satu grafik pendek sedangkan yang lain panjang).

Pertanyaan:
Bagaimana saya bisa melakukan ini? Saya belum menikah dengan grid.arrange tetapi ggplot2 adalah suatu keharusan.

Apa yang telah saya coba:
Saya mencoba bermain dengan lebar dan tinggi serta ncol dan nrow untuk membuat kisi 2 x 2 dan menempatkan visual di sudut yang berlawanan dan kemudian bermain dengan lebar tetapi saya tidak bisa mendapatkan visual di sudut yang berlawanan .

require(ggplot2);require(gridExtra)
A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 
grid.arrange(A, B, ncol=1)

masukkan deskripsi gambar di sini

Tyler Rinker
sumber
2
Berikut dua kemungkinan opsi: di sini dan di sini .
joran
@Joran Saya mencari sumbu kiri untuk disejajarkan. Saya tidak berpikir ini akan melakukannya. Tapi aku ingin salah.
Tyler Rinker

Jawaban:

132

Coba ini,

 gA <- ggplotGrob(A)
 gB <- ggplotGrob(B)
 maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
 gA$widths[2:5] <- as.list(maxWidth)
 gB$widths[2:5] <- as.list(maxWidth)
 grid.arrange(gA, gB, ncol=1)

Edit

Berikut adalah solusi yang lebih umum (bekerja dengan sejumlah plot) menggunakan versi modifikasi yang rbind.gtabledisertakan dalamgridExtra

gA <- ggplotGrob(A)
gB <- ggplotGrob(B)
grid::grid.newpage()
grid::grid.draw(rbind(gA, gB))
baptiste
sumber
3
Cantik dan sangat lurus ke depan. Terima kasih atas solusinya.
Tyler Rinker
1
Solusi yang tepat! Saya telah mencari sesuatu seperti ini untuk menyelaraskan beberapa plot deret waktu terpisah yang tidak dapat saya lakukan dengan faceting karena kustomisasi utama di setiap plot.
wahalulu
Apakah Anda akan berbaik hati memberikan cara yang sesuai untuk mencocokkan ketinggian jika kita memiliki dua kolom? gA $ heights [2: 3] tampaknya tidak berfungsi. Apakah saya harus memilih elemen grob lain selain 2: 3? Terima kasih!
Etienne Low-Décarie
4
Terima kasih atas solusi Anda, Baptiste. Namun, saya tidak mendapatkan ini untuk bekerja ketika salah satu plot adalah a tableGrob. The gtable::cbindmemberi saya sebuah kesalahan mengecewakan: nrow(x) == nrow(y) is not TRUE. Ada saran?
Gabra
2
Solusi ini berhasil untuk saya, taruh saya mencoba memahaminya. Untuk apa [2:5]berdiri?
Hurlikus
38

Saya ingin menggeneralisasi ini untuk sejumlah plot. Berikut adalah solusi langkah demi langkah menggunakan pendekatan oleh Baptiste:

plots <- list(A, B, C, D)
grobs <- list()
widths <- list()

kumpulkan lebar untuk setiap grob di setiap plot

for (i in 1:length(plots)){
    grobs[[i]] <- ggplotGrob(plots[[i]])
    widths[[i]] <- grobs[[i]]$widths[2:5]
}

gunakan do.call untuk mendapatkan lebar maksimal

maxwidth <- do.call(grid::unit.pmax, widths)

tetapkan lebar maksimal untuk setiap grob

for (i in 1:length(grobs)){
     grobs[[i]]$widths[2:5] <- as.list(maxwidth)
}

merencanakan

do.call("grid.arrange", c(grobs, ncol = 1))
slizb
sumber
2
Berfungsi bahkan ketika plot memiliki legenda dengan lebar yang bervariasi - sangat bagus!
Keith Hughitt
30

Menggunakan paket cowplot :

A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 

library(cowplot)
plot_grid(A, B, ncol=1, align="v")

masukkan deskripsi gambar di sini

zx8754
sumber
12

Di http://rpubs.com/MarkusLoew/13295 adalah solusi yang sangat mudah tersedia (item terakhir) Diterapkan untuk masalah ini:

require(ggplot2);require(gridExtra)
A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 
grid.draw(rbind(ggplotGrob(A), ggplotGrob(B), size="first"))

Anda juga dapat menggunakan ini untuk lebar dan tinggi:

require(ggplot2);require(gridExtra)
A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 
C <- ggplot(CO2, aes(x=conc)) + geom_bar() +coord_flip()
D <- ggplot(CO2, aes(x=uptake)) + geom_bar() +coord_flip() 
grid.draw(cbind(
            rbind(ggplotGrob(A), ggplotGrob(B), size="first"),
            rbind(ggplotGrob(C), ggplotGrob(D), size="first"),
            size='first'))
Wilbert
sumber
2
menggunakan size="first"berarti bahwa penyelarasan tidak akan terlihat sangat baik jika plot kedua lebih besar dari yang pertama
baptiste
10

The eggpaket membungkus ggplot objek menjadi standar 3x3gtable, memungkinkan penyelarasan panel plot antara ggplots sewenang-wenang, termasuk yang facetted.

library(egg) # devtools::install_github('baptiste/egg')
library(ggplot2)

p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
  geom_point() 

p2 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
  geom_point() + facet_wrap( ~ cyl, ncol=2, scales = "free") +
  guides(colour="none") +
  theme()

ggarrange(p1, p2)

masukkan deskripsi gambar di sini

baptiste
sumber
bagi saya ini bisa dengan baik mengatur secara horizontal peta panas sederhana ( geom_tile) dengan legenda di bagian bawah dan peta panas multifaset ( facet_griddengan geom_tile), tetapi gagal untuk menyelaraskan ketinggian plot ketiga, yang merupakan dendrogram ( geom_segment). Namun, cowplot atau gridExtra::grid.arrangebahkan tidak mampu melakukan yang pertama, jadi sejauh ini yang terbaik
deeenes
8

Berikut adalah solusi lain yang mungkin menggunakan meltdari paket reshape2, dan facet_wrap:

library(ggplot2)
library(reshape2)

dat = CO2[, c(1, 2)]
dat$id = seq(nrow(dat))
mdat = melt(dat, id.vars="id")

head(mdat)
#   id variable value
# 1  1    Plant   Qn1
# 2  2    Plant   Qn1
# 3  3    Plant   Qn1
# 4  4    Plant   Qn1
# 5  5    Plant   Qn1
# 6  6    Plant   Qn1

plot_1 = ggplot(mdat, aes(x=value)) + 
         geom_bar() + 
         coord_flip() +
         facet_wrap(~ variable, nrow=2, scales="free", drop=TRUE)

ggsave(plot=plot_1, filename="plot_1.png", height=4, width=6)

masukkan deskripsi gambar di sini

bdemarest
sumber
Solusi ini mengasumsikan Anda memiliki jumlah baris yang sama di setiap kolom. Di MRWE saya itu benar tetapi tidak dalam kenyataan.
Tyler Rinker
Saya tidak yakin saya mengerti: Apakah yang Anda maksud bahwa CO2 $ Plant dan CO2 $ Type kebetulan memiliki panjang yang sama, tetapi data Anda yang sebenarnya tidak seperti itu?
bdemarest
Ini adalah dua kumpulan data berbeda yang berbagi satu variabel sehingga jumlah baris tidak sama.
Tyler Rinker
2

The tambal sulam paket menangani ini secara default:

library(ggplot2)
library(patchwork)

A <- ggplot(CO2, aes(x = Plant)) + geom_bar() + coord_flip() 
B <- ggplot(CO2, aes(x = Type)) + geom_bar() + coord_flip() 

A / B

Dibuat pada 2019-12-08 oleh paket reprex (v0.3.0)

MSR
sumber
0

Paling banter ini adalah retasan:

library(wq)
layOut(list(A, 1, 2:16),  list(B, 2:3, 1:16))

Rasanya sangat salah.

Tyler Rinker
sumber
-1

Saya tahu ini adalah posting lama, dan itu telah dijawab, tetapi izinkan saya menyarankan untuk menggabungkan pendekatan @ baptiste dengan purrragar terlihat lebih bagus:

library(purrr)
list(A, B) %>% 
  map(ggplotGrob) %>% 
  do.call(gridExtra::gtable_rbind, .) %>% 
  grid::grid.draw()
Felipe Gerard
sumber