2013-04-27 26 views
39

Tôi có một vài danh mục khác nhau mà tôi muốn vẽ. Đây là các loại khác nhau, mỗi danh mục có bộ nhãn riêng, nhưng có ý nghĩa để nhóm lại với nhau trong tài liệu. Sau đây cung cấp cho một số đơn giản thanh biểu đồ ví dụ xếp chồng lên nhau:Làm cách nào để tạo các ô có chiều rộng nhất quán trong ggplot (với truyền thuyết)?

df <- data.frame(x=c("a", "b", "c"), 
       y=c("happy", "sad", "ambivalent about life")) 
ggplot(df, aes(x=factor(0), fill=x)) + geom_bar() 
ggplot(df, aes(x=factor(0), fill=y)) + geom_bar() 

Vấn đề là với các nhãn khác nhau, những huyền thoại có độ rộng khác nhau, có nghĩa là lô có độ rộng khác nhau, dẫn đến việc tìm kiếm một chút ngốc nghếch nếu tôi thực hiện một bảng hoặc \subfigure yếu tố. Làm thế nào tôi có thể sửa lỗi này?

Có cách nào để đặt rõ ràng chiều rộng (tuyệt đối hoặc tương đối) của ô hoặc chú giải không?

Chart 1 based on x (wider) Chart 2 based on y (narrower)

+2

thay thế khác: bạn có thể có thể đặt những huyền thoại ở phía trên/dưới/bên trong cốt truyện? – Arun

+4

'+ chủ đề (legend.position =" top ")' (hoặc "bottom") (hoặc) '+ theme (legend.position = c (1.0), legend.justification = c (1.0))' – Arun

Trả lời

30

Edit: Rất dễ dàng với egg gói sẵn tại github

# install.package(devtools) 
# devtools::install_github("baptiste/egg") 

library(egg) 

p1 <- ggplot(data.frame(x=c("a","b","c"), 
         y=c("happy","sad","ambivalent about life")), 
      aes(x=factor(0),fill=x)) + 
     geom_bar() 
p2 <- ggplot(data.frame(x=c("a","b","c"), 
         y=c("happy","sad","ambivalent about life")), 
      aes(x=factor(0),fill=y)) + 
     geom_bar() 

ggarrange(p1,p2, ncol = 1) 

gốc Udated để ggplot2 2.2.1

Dưới đây là một giải pháp mà sử dụng các chức năng từ gói gtable và tập trung vào chiều rộng của các hộp chú giải. (Một giải pháp tổng quát hơn có thể được tìm thấy here.)

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

# Your plots 
p1 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=x)) + geom_bar() 
p2 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=y)) + geom_bar() 

# Get the gtables 
gA <- ggplotGrob(p1) 
gB <- ggplotGrob(p2) 

# Set the widths 
gA$widths <- gB$widths 

# Arrange the two charts. 
# The legend boxes are centered 
grid.newpage() 
grid.arrange(gA, gB, nrow = 2) 

Nếu ngoài ra, các hộp huyền thoại cần phải được canh hàng trái, và vay một số mã từ here được viết bởi @Julius

p1 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=x)) + geom_bar() 
p2 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=y)) + geom_bar() 

# Get the widths 
gA <- ggplotGrob(p1) 
gB <- ggplotGrob(p2) 

# The parts that differs in width 
leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm") 
leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm") 

# Set the widths 
gA$widths <- gB$widths 

# Add an empty column of "abs(diff(widths)) mm" width on the right of 
# legend box for gA (the smaller legend box) 
gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm")) 

# Arrange the two charts 
grid.newpage() 
grid.arrange(gA, gB, nrow = 2) 

enter image description here

Giải pháp thay thế Có các chức năng rbindcbind trong gói gtable để kết hợp Gro bs thành một grob. Đối với các biểu đồ ở đây, chiều rộng phải được đặt bằng cách sử dụng size = "max", nhưng phiên bản CRAN là gtable sẽ phát ra lỗi.

Một tùy chọn: Rõ ràng là chú thích trong ô thứ hai rộng hơn. Do đó, hãy sử dụng tùy chọn size = "last".

# Get the grobs 
gA <- ggplotGrob(p1) 
gB <- ggplotGrob(p2) 

# Combine the plots 
g = rbind(gA, gB, size = "last") 

# Draw it 
grid.newpage() 
grid.draw(g) 

canh trái huyền thoại:

# Get the grobs 
gA <- ggplotGrob(p1) 
gB <- ggplotGrob(p2) 

# The parts that differs in width 
leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm") 
leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm") 

# Add an empty column of "abs(diff(widths)) mm" width on the right of 
# legend box for gA (the smaller legend box) 
gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm")) 

# Combine the plots 
g = rbind(gA, gB, size = "last") 

# Draw it 
grid.newpage() 
grid.draw(g) 

Một lựa chọn thứ hai là sử dụng rbind từ gói gridExtra Baptiste của

# Get the grobs 
gA <- ggplotGrob(p1) 
gB <- ggplotGrob(p2) 

# Combine the plots 
g = gridExtra::rbind.gtable(gA, gB, size = "max") 

# Draw it 
grid.newpage() 
grid.draw(g) 

canh trái huyền thoại:

# Get the grobs 
gA <- ggplotGrob(p1) 
gB <- ggplotGrob(p2) 

# The parts that differs in width 
leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm") 
leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm") 

# Add an empty column of "abs(diff(widths)) mm" width on the right of 
# legend box for gA (the smaller legend box) 
gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm")) 

# Combine the plots 
g = gridExtra::rbind.gtable(gA, gB, size = "max") 

# Draw it 
grid.newpage() 
grid.draw(g) 
+1

Thật tuyệt vời! Các hàm và biến này có được ghi lại ở bất cứ đâu hoặc bạn chỉ cần xem qua nguồn 'ggplot'? –

+0

@ jamie.f.olson Có [cẩm nang gtable] (http://cran.r-project.org/web/packages/gtable/index.html) trên CRAN, nhưng ngoài ra, đó là vấn đề lấy lưu ý các ví dụ của người khác về SO và đôi khi trên [danh sách gửi thư ggplot] (https://groups.google.com/forum/?hl=vi&fromgroups#!forum/ggplot2). –

+1

Bạn đã thử 'rbind()' ing các ô với nhau chưa? Điều đó chỉ nên làm việc, nhưng tôi không thể nhớ nếu chúng ta đã hoàn thành mã đó. – hadley

8

Như @hadley thấy, rbind.gtable nên có thể xử lý này,

grid.draw(rbind(ggplotGrob(p1), ggplotGrob(p2), size="last")) 

tuy nhiên, độ rộng bố trí lý tưởng nên được size="max", mà doesn't cope well với một số loại đơn vị lưới.

+0

Là: 'Lỗi trong mmm

+0

bạn cần chạy mã mẫu để xem – baptiste

1

Chỉ cần tình cờ, tôi nhận thấy rằng giải pháp của Arun mà anh ta gợi ý trong các bình luận của anh ấy đã không được chọn. Tôi cảm thấy cách tiếp cận đơn giản và hiệu quả của anh ấy thực sự đáng để minh họa.

Arun gợi ý để di chuyển các huyền thoại xuống đáy đầu hoặc:

ggplot(df, aes(x=factor(0), fill=x)) + geom_bar() + theme(legend.position = "bottom") 
ggplot(df, aes(x=factor(0), fill=y)) + geom_bar() + theme(legend.position = "bottom") 

enter image description here enter image description here

Bây giờ, các lô có chiều rộng tương tự như yêu cầu. Ngoài ra, diện tích ô có kích thước bằng nhau trong cả hai trường hợp.

Nếu có nhiều yếu tố hơn hoặc thậm chí là nhãn dài hơn, có thể cần thiết để chơi xung quanh với chú giải, ví dụ: để hiển thị chú thích trong hai hàng quặng trở lên. theme()guide_legend() có một số thông số để kiểm soát vị trí và sự xuất hiện của truyền thuyết trong ggplot2.

5

Gói cowplot cũng có align_plots chức năng cho mục đích này (đầu ra không được hiển thị),

both2 <- align_plots(p1, p2, align="hv", axis="tblr") 
p1x <- ggdraw(both2[[1]]) 
p2x <- ggdraw(both2[[2]]) 
save_plot("cow1.png", p1x) 
save_plot("cow2.png", p2x) 

và cũng plot_grid giúp tiết kiệm lô đến cùng một tập tin.

library(cowplot) 
both <- plot_grid(p1, p2, ncol=1, labels = c("A", "B"), align = "v") 
save_plot("cow.png", both) 

enter image description here

Các vấn đề liên quan