จัดชิดขอบกราฟสองด้านซ้าย (ggplot)


105

ฉันใช้ ggplot และมีกราฟสองกราฟที่ฉันต้องการแสดงด้านบนของกันและกัน ฉันใช้grid.arrangeจาก gridExtra เพื่อวางซ้อนกัน ปัญหาคือฉันต้องการให้ขอบด้านซ้ายของกราฟจัดแนวเช่นเดียวกับขอบด้านขวาโดยไม่คำนึงถึงป้ายกำกับแกน (ปัญหาเกิดขึ้นเนื่องจากป้ายกำกับของกราฟหนึ่งสั้นในขณะที่อีกกราฟหนึ่งยาว)

คำถาม:
ฉันจะทำสิ่งนี้ได้อย่างไร? ฉันไม่ได้แต่งงานกับกริดจัด แต่ ggplot2 เป็นสิ่งจำเป็น

สิ่งที่ฉันได้ลอง:
ฉันลองเล่นกับความกว้างและความสูงเช่นเดียวกับ ncol และ nrow เพื่อสร้างตาราง 2 x 2 และวางภาพในมุมตรงข้ามจากนั้นเล่นกับความกว้าง แต่ฉันไม่สามารถรับภาพในมุมตรงข้ามได้ .

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)

ป้อนคำอธิบายภาพที่นี่


2
ที่นี่สองตัวเลือกที่เป็นไปได้ที่นี่และที่นี่
joran

@Joran ฉันกำลังมองหาแกนด้านซ้ายที่จะจัดแนว ฉันไม่คิดว่าสิ่งเหล่านี้จะทำได้ ฉันอยากจะผิด
Tyler Rinker

คำตอบ:


133

ลองสิ่งนี้

 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)

แก้ไข

นี่เป็นวิธีแก้ปัญหาทั่วไปมากขึ้น (ใช้ได้กับพล็อตจำนวนเท่าใดก็ได้) โดยใช้เวอร์ชันแก้ไขที่rbind.gtableรวมอยู่ในgridExtra

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

3
ตรงไปตรงมาสวยและน่ารักจริงๆ ขอบคุณสำหรับวิธีแก้ปัญหา
Tyler Rinker

1
โซลูชั่นที่สมบูรณ์แบบ! ฉันกำลังมองหาบางอย่างเช่นนี้เพื่อจัดแนวพล็อตอนุกรมเวลาที่แยกจากกันซึ่งฉันไม่สามารถทำกับ faceting ได้เนื่องจากการปรับแต่งที่สำคัญในแต่ละพล็อต
wahalulu

คุณจะกรุณาให้สิ่งที่จะจับคู่ความสูงได้หรือไม่ถ้าเรามีสองคอลัมน์? gA $ heights [2: 3] ดูเหมือนจะไม่ทำงาน ฉันต้องเลือกองค์ประกอบอื่นของ grob มากกว่า 2: 3 หรือไม่? ขอบคุณ!
Etienne Low-Décarie

4
ขอบคุณสำหรับการแก้ปัญหาของคุณ Baptiste อย่างไรก็ตามฉันไม่สามารถใช้งานได้เมื่อหนึ่งในแปลงเป็นไฟล์tableGrob. ให้ฉันข้อผิดพลาดที่น่าผิดหวัง:gtable::cbind nrow(x) == nrow(y) is not TRUEข้อเสนอแนะใด ๆ ?
Gabra

2
วิธีนี้ใช้ได้ผลสำหรับฉันฉันพยายามที่จะเข้าใจมัน ย่อมาจากอะไร[2:5]?
Hurlikus

38

ฉันต้องการสรุปสิ่งนี้สำหรับพล็อตจำนวนเท่าใดก็ได้ นี่คือวิธีแก้ปัญหาทีละขั้นตอนโดยใช้แนวทางของ Baptiste:

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

รวบรวมความกว้างสำหรับแต่ละร่องของแต่ละพล็อต

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

ใช้ do.call เพื่อรับความกว้างสูงสุด

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

กำหนดความกว้างสูงสุดให้กับแต่ละ grob

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

พล็อต

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

2
ใช้งานได้แม้ว่าพล็อตจะมีตำนานที่มีความกว้างต่างกัน - ดีมาก!
Keith Hughitt

31

การใช้แพ็คเกจ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")

ป้อนคำอธิบายภาพที่นี่


12

บนhttp://rpubs.com/MarkusLoew/13295เป็นวิธีแก้ปัญหาที่ง่ายมาก (รายการสุดท้าย) นำไปใช้กับปัญหานี้:

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

คุณยังสามารถใช้ทั้งความกว้างและความสูง:

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
การใช้size="first"หมายความว่าการจัดตำแหน่งจะดูไม่ดีนักหากพล็อตที่สองใหญ่กว่าครั้งแรก
baptiste

10

eggwraps แพคเกจ ggplot วัตถุเป็นมาตรฐาน3x3gtable ช่วยให้การจัดตำแหน่งของแผงล็อตระหว่าง ggplots พลรวมทั้งคน 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)

ป้อนคำอธิบายภาพที่นี่


สำหรับฉันสิ่งนี้สามารถจัดเรียงแผนที่ความร้อนอย่างง่าย ( geom_tile) ในแนวนอนได้อย่างเหมาะสมโดยมีคำอธิบายแผนภูมิที่ด้านล่างและแผนที่ความร้อนหลายแง่มุม ( facet_gridมีgeom_tile) แต่ล้มเหลวในการจัดแนวความสูงของพล็อตที่สามซึ่งเป็น dendrogram ( geom_segment) อย่างไรก็ตาม cowplot หรือgridExtra::grid.arrangeไม่สามารถทำได้แม้ในอดีตดังนั้นสิ่งนี้จึงดีที่สุด
deeenes

8

นี่เป็นอีกวิธีหนึ่งที่เป็นไปได้โดยใช้meltจากแพ็คเกจ reshape2 และ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)

ป้อนคำอธิบายภาพที่นี่


วิธีนี้ถือว่าคุณมีจำนวนแถวเท่ากันในแต่ละคอลัมน์ ใน MRWE ของฉันนั่นเป็นความจริง แต่ไม่ใช่ในความเป็นจริง
Tyler Rinker

ฉันไม่แน่ใจว่าฉันเข้าใจ: คุณหมายความว่า CO2 $ Plant และ CO2 $ Type มีความยาวเท่ากัน แต่ข้อมูลจริงของคุณไม่เป็นเช่นนั้น?
bdemarest

เป็นชุดข้อมูลที่แตกต่างกันสองชุดที่แชร์ตัวแปรเดียวจำนวนแถวจึงไม่เหมือนกัน
Tyler Rinker



-1

ฉันรู้ว่านี่เป็นโพสต์เก่าและได้รับคำตอบแล้ว แต่ฉันขอแนะนำให้รวมแนวทางของ @ baptiste เข้าด้วยกันpurrrเพื่อให้ดูดีขึ้น:

library(purrr)
list(A, B) %>% 
  map(ggplotGrob) %>% 
  do.call(gridExtra::gtable_rbind, .) %>% 
  grid::grid.draw()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.