İki grafik kenarını sola hizala (ggplot)


105

Ggplot kullanıyorum ve üst üste görüntülemek istediğim iki grafiğim var. grid.arrangeOnları istiflemek için gridExtra'dan kullandım . Sorun şu ki, eksen etiketleri ne olursa olsun grafiklerin sol kenarlarının yanı sıra sağ kenarlarının da hizalanmasını istiyorum. (sorun, bir grafiğin etiketlerinin kısa, diğerinin uzun olması nedeniyle ortaya çıkar).

Soru:
Bunu nasıl yapabilirim? Grid.arrange ile evli değilim ama ggplot2 bir zorunluluktur.

Denediğim şey:
2 x 2 ızgara yapmak için ncol ve nrow'un yanı sıra genişlik ve yükseklik ile oynamayı ve görselleri zıt köşelere yerleştirmeyi ve sonra genişliklerle oynamayı denedim ancak zıt köşelerde görselleri alamadım .

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)

görüntü açıklamasını buraya girin


2
İşte iki olası seçenek: burada ve burada .
joran

@Joran Sol eksenlerin hizalanmasını arıyorum. Bunların işe yarayacağını sanmıyorum. Yine de yanılmak isterim.
Tyler Rinker

Yanıtlar:


132

Bunu dene,

 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)

Düzenle

Burada, rbind.gtabledahil edilenin değiştirilmiş bir sürümünü kullanan daha genel bir çözüm (herhangi bir sayıda grafikle çalışır) .gridExtra

gA <- ggplotGrob(A)
gB <- ggplotGrob(B)
grid::grid.newpage()
grid::grid.draw(rbind(gA, gB))

3
Güzel ve gerçekten oldukça yalındır. Çözüm için teşekkürler.
Tyler Rinker

1
Mükemmel çözüm! Her arsadaki büyük özelleştirme nedeniyle fasetleme ile yapamayacağım birden fazla ayrı zaman serisi grafiğini hizalamak için bunun gibi bir şey arıyordum.
wahalulu

İki sütunumuz olsaydı yüksekliği eşleştirmenin yolunun ne olacağını söyler misiniz? gA $ heights [2: 3] çalışmıyor gibi görünüyor. Grobun 2: 3'ten başka bir öğesini seçmem gerekir mi? Teşekkür ederim!
Etienne Low-Décarie

4
Baptiste çözümün için teşekkürler. Ancak, arazilerden biri a tableGrob. gtable::cbindBana bir hayal kırıklığı hata veriyor: nrow(x) == nrow(y) is not TRUE. Baska öneri?
Gabra

2
Bu çözüm benim için çalıştı, onu anlamaya çalışıyorum. Ne anlama geliyor [2:5]?
Hurlikus

38

Bunu herhangi bir sayıdaki olay örgüsü için genellemek istedim. İşte Baptiste'in yaklaşımını kullanarak adım adım bir çözüm:

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

her grafiğin her bir parçası için genişlikleri toplayın

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

maksimum genişliği elde etmek için do.call kullanın

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

her bir grob için maksimum genişliği atayın

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

arsa

do.call("grid.arrange", c(grobs, ncol = 1))

2
Arsaların çeşitli genişliklerde efsaneleri olsa bile işe yarar - çok güzel!
Keith Hughitt

30

Cowplot paketini kullanma :

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

görüntü açıklamasını buraya girin


12

Http://rpubs.com/MarkusLoew/13295 adresinde gerçekten kolay bir çözüm mevcut (son madde) Bu soruna uygulanan:

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

bunu hem genişlik hem de yükseklik için de kullanabilirsiniz:

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

2
kullanmak size="first", eğer ikinci olay birinciden daha büyükse hizalamanın çok iyi görünmeyeceği anlamına gelir
baptiste

10

eggBir standart nesnelerini ggplot paketi saran 3x3yontulmuş da dahil olmak üzere rasgele ggplots arasında arsa panellerin uyum sağlayan gtable.

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)

görüntü açıklamasını buraya girin


benim için bu geom_tile, altta gösterge ve çok yönlü bir ısı haritası ( facet_gridile geom_tile) olan basit bir ısı haritasını ( ) yatay olarak düzgün bir şekilde düzenleyebilirdi , ancak bir dendrogram ( geom_segment) olan üçüncü grafiğin yüksekliğini hizalamayı başaramadı . ancak, inek planı ya gridExtra::grid.arrangeda eskisini bile yapamadı, bu yüzden bu şimdiye kadarki en iyi çalışıyor
deeenes

8

meltReshape2 paketini kullanarak başka bir olası çözüm ve 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)

görüntü açıklamasını buraya girin


Bu çözüm, her sütunda eşit sayıda satırınız olduğunu varsayar. MRWE'mde bu doğru ama gerçekte değil.
Tyler Rinker

Anladığımdan emin değilim: CO2 $ Plant ve CO2 $ Type'ın aynı uzunlukta olduğunu, ancak gerçek verilerinizin böyle olmadığını mı söylüyorsunuz?
bdemarest

Bir değişkeni paylaşan iki farklı veri kümesidir, bu nedenle satır sayısı aynı değildir.
Tyler Rinker

2

Patchwork paket varsayılan olarak bu işler:

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

2019-12-08 tarihinde reprex paketi (v0.3.0) tarafından oluşturuldu


0

En iyi ihtimalle bu bir hack:

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

Yine de gerçekten yanlış geliyor.


-1

Bunun eski bir gönderi olduğunu ve zaten yanıtlanmış olduğunu biliyorum, ancak purrrdaha güzel görünmesi için @ baptiste'nin yaklaşımını birleştirmeyi önerebilir miyim :

library(purrr)
list(A, B) %>% 
  map(ggplotGrob) %>% 
  do.call(gridExtra::gtable_rbind, .) %>% 
  grid::grid.draw()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.