Căn trái hai cạnh biểu đồ (ggplot)


105

Tôi đang sử dụng ggplot và có hai biểu đồ mà tôi muốn hiển thị chồng lên nhau. Tôi đã sử dụng grid.arrangetừ gridExtra để xếp chúng. Vấn đề là tôi muốn các cạnh bên trái của đồ thị được căn chỉnh cũng như các cạnh bên phải bất kể nhãn trục. (vấn đề nảy sinh vì các nhãn của một biểu đồ ngắn trong khi nhãn kia dài).

Câu hỏi:
Làm thế nào tôi có thể làm điều này? Tôi chưa kết hôn với grid.arrange nhưng ggplot2 là phải.

Những gì tôi đã thử:
Tôi đã thử chơi với chiều rộng và chiều cao cũng như ncol và nrow để tạo lưới 2 x 2 và đặt hình ảnh ở các góc đối diện và sau đó chơi với độ rộng nhưng tôi không thể có được hình ảnh ở các góc đối diện .

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)

nhập mô tả hình ảnh ở đây


2
Đây là hai lựa chọn khả thi: đâyđây .
joran

@Joran Tôi đang tìm các trục bên trái được căn chỉnh. Tôi không nghĩ những thứ này sẽ làm được. Mặc dù vậy, tôi muốn sai.
Tyler Rinker

Câu trả lời:


132

Thử cái này,

 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)

Biên tập

Đây là một giải pháp chung hơn (hoạt động với bất kỳ số lượng lô đất nào) bằng cách sử dụng phiên bản sửa đổi của rbind.gtablebao gồm tronggridExtra

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

3
Đẹp và thực sự khá thẳng về phía trước. Cảm ơn bạn cho giải pháp.
Tyler Rinker

1
Giải pháp hoàn hảo! Tôi đang tìm kiếm thứ gì đó như thế này để căn chỉnh nhiều ô của chuỗi thời gian riêng biệt mà tôi không thể thực hiện với việc ghép mặt vì sự tùy chỉnh chính trong mỗi cốt truyện.
wahalulu

Bạn có vui lòng cung cấp cách nào để khớp với chiều cao nếu chúng ta có hai cột không? gA $ heights [2: 3] dường như không hoạt động. Tôi có phải chọn một phần tử khác của háng ngoài 2: 3 không? Cảm ơn bạn!
Etienne Low-Décarie

4
Cảm ơn bạn cho giải pháp của bạn Baptiste. Tuy nhiên, tôi không làm được điều này khi một trong các âm mưu là a tableGrob. Các gtable::cbindmang lại cho tôi một lỗi đáng thất vọng: nrow(x) == nrow(y) is not TRUE. Bất kỳ đề xuất?
Gabra

2
Giải pháp này đã hiệu quả với tôi, tôi đang cố gắng hiểu nó. Cái gì [2:5]đứng cho?
Hurlikus

38

Tôi muốn tổng quát điều này cho bất kỳ số lượng âm mưu nào. Đây là giải pháp từng bước sử dụng phương pháp của Baptiste:

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

thu thập các chiều rộng cho mỗi hàng của mỗi ô

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

sử dụng do.call để có được chiều rộng tối đa

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

chỉ định chiều rộng tối đa cho mỗi bẹn

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

âm mưu

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

2
Hoạt động ngay cả khi các ô có truyền thuyết về độ rộng khác nhau - rất tuyệt!
Keith Hughitt 19/09/16

30

Sử dụng gói 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")

nhập mô tả hình ảnh ở đây


12

Trên http://rpubs.com/MarkusLoew/13295 là một giải pháp thực sự dễ dàng có sẵn (mục cuối cùng) Được áp dụng cho vấn đề này:

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

bạn cũng có thể sử dụng nó cho cả chiều rộng và chiều cao:

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
sử dụng size="first"phương tiện mà sự liên kết sẽ không nhìn rất tốt nếu âm mưu thứ hai là lớn hơn là người đầu tiên
Baptiste

10

Các eggliệu pháp quấn gói ggplot đối tượng thành một chuẩn 3x3gtable, tạo điều kiện cho sự liên kết của các tấm cốt truyện giữa ggplots tùy ý, bao gồm cả những 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)

nhập mô tả hình ảnh ở đây


đối với tôi, điều này có thể sắp xếp theo chiều ngang một bản đồ nhiệt đơn giản ( geom_tile) với chú giải ở dưới cùng và một bản đồ nhiệt nhiều mặt ( facet_gridvới geom_tile), nhưng không thể căn chỉnh chiều cao của ô thứ ba, đó là một hình ảnh ( geom_segment). Tuy nhiên, cowplot hoặc gridExtra::grid.arrangekhông thể làm ngay cả những cựu, vì vậy công trình này là tốt nhất cho đến nay
deeenes

8

Đây là một giải pháp khả thi khác bằng cách sử dụng meltgói reshape2 và 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)

nhập mô tả hình ảnh ở đây


Giải pháp này giả định bạn có số hàng trong mỗi cột bằng nhau. Trong MRWE của tôi điều đó đúng nhưng không phải trong thực tế.
Tyler Rinker

Tôi không chắc mình hiểu: Ý của bạn là CO2 $ Plant và CO2 $ Type có cùng độ dài, nhưng dữ liệu thực tế của bạn lại không như vậy?
bdemhest

Đó là hai tập dữ liệu khác nhau chia sẻ một biến nên số hàng không giống nhau.
Tyler Rinker

2

Các chắp vá gói xử lý này theo mặc định:

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

Được tạo vào ngày 12 tháng 12 năm 2019 bởi gói reprex (v0.3.0)


0

Tốt nhất đây là một vụ hack:

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

Nó thực sự cảm thấy sai mặc dù.


-1

Tôi biết đây là một bài đăng cũ và nó đã được trả lời, nhưng tôi có thể đề nghị kết hợp cách tiếp cận của @ baptiste purrrđể làm cho nó trông đẹp hơn:

library(purrr)
list(A, B) %>% 
  map(ggplotGrob) %>% 
  do.call(gridExtra::gtable_rbind, .) %>% 
  grid::grid.draw()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.