Câu trả lời cho câu hỏi này nằm trong các gói grid
và gtable
. Tất cả mọi thứ trong cốt truyện được đặt ra theo một thứ tự cụ thể và bạn có thể tìm thấy nơi mà tất cả mọi thứ là nếu bạn đào một chút.
library('gtable')
library('grid')
library('magrittr') # for the %>% that I love so well
# First get the grob
z <- ggplotGrob(p)
Mục tiêu cuối cùng của thao tác này là che phủ nhãn trên cùng, nhưng mẹo là cả hai mặt này tồn tại trên cùng một hàng trong không gian lưới. Họ là một bảng trong một bảng (nhìn vào các hàng với cái tên "dải", cũng lưu ý các zeroGrob
, chúng sẽ có ích sau):
z
## TableGrob (13 x 14) "layout": 34 grobs
## z cells name grob
## 1 0 (1-13, 1-14) background rect[plot.background..rect.522]
## 2 1 (7- 7, 4- 4) panel-1-1 gTree[panel-1.gTree.292]
...
## 20 3 (7- 7,12-12) axis-r-1 zeroGrob[NULL]
## 21 3 (9- 9,12-12) axis-r-2 zeroGrob[NULL]
## 22 2 (6- 6, 4- 4) strip-t-1 gtable[strip]
## 23 2 (6- 6, 6- 6) strip-t-2 gtable[strip]
## 24 2 (6- 6, 8- 8) strip-t-3 gtable[strip]
## 25 2 (6- 6,10-10) strip-t-4 gtable[strip]
## 26 2 (7- 7,11-11) strip-r-1 gtable[strip]
## 27 2 (9- 9,11-11) strip-r-2 gtable[strip]
...
## 32 8 (3- 3, 4-10) subtitle zeroGrob[plot.subtitle..zeroGrob.519]
## 33 9 (2- 2, 4-10) title zeroGrob[plot.title..zeroGrob.518]
## 34 10 (12-12, 4-10) caption zeroGrob[plot.caption..zeroGrob.520]
Nếu bạn phóng to các dải đầu tiên, bạn có thể thấy cấu trúc lồng nhau:
z$grob[[22]]
## TableGrob (2 x 1) "strip": 2 grobs
## z cells name grob
## 1 1 (1-1,1-1) strip absoluteGrob[strip.absoluteGrob.451]
## 2 2 (2-2,1-1) strip absoluteGrob[strip.absoluteGrob.475]
Đối với mỗi grob, chúng tôi có một đối tượng liệt kê thứ tự mà nó vẽ (z), vị trí trong lưới (tế bào), một nhãn (tên) và hình học (grob).
Vì chúng tôi có thể tạo gtables trong gtables, chúng tôi sẽ sử dụng điều này để vẽ trên lô gốc của chúng tôi. Đầu tiên, chúng ta cần phải tìm các vị trí trong cốt truyện cần thay thế.
# Find the location of the strips in the main plot
locations <- grep("strip-t", z$layout$name)
# Filter out the strips (trim = FALSE is important here for positions relative to the main plot)
strip <- gtable_filter(z, "strip-t", trim = FALSE)
# Gathering our positions for the main plot
top <- strip$layout$t[1]
l <- strip$layout$l[c(1, 3)]
r <- strip$layout$r[c(2, 4)]
Khi chúng tôi có vị trí, chúng tôi cần tạo bảng thay thế. Chúng ta có thể làm điều này với một ma trận các danh sách (có, nó là lạ. Chỉ cần cuộn với nó). Ma trận này cần phải có ba cột và hai hàng trong trường hợp của chúng tôi vì hai khía cạnh và khoảng cách giữa chúng. Vì chúng ta chỉ là đi để thay thế dữ liệu trong ma trận sau, chúng ta sẽ tạo ra một với zeroGrob
s:
mat <- matrix(vector("list", length = 6), nrow = 2)
mat[] <- list(zeroGrob())
# The separator for the facets has zero width
res <- gtable_matrix("toprow", mat, unit(c(1, 0, 1), "null"), unit(c(1, 1), "null"))
Mặt nạ được tạo ra theo hai bước, bao gồm các nhóm khía cạnh đầu tiên và sau đó là thứ hai. Trong phần đầu tiên, chúng tôi đang sử dụng vị trí chúng tôi ghi lại trước đó để lấy grob thích hợp từ ô gốc và thêm nó lên trên ma trận thay thế res
của chúng tôi, kéo dài toàn bộ chiều dài. Sau đó chúng tôi thêm ma trận đó vào đầu cốt truyện của chúng tôi.
# Adding the first layer
zz <- res %>%
gtable_add_grob(z$grobs[[locations[1]]]$grobs[[1]], 1, 1, 1, 3) %>%
gtable_add_grob(z, ., t = top, l = l[1], b = top, r = r[1], name = c("add-strip"))
# Adding the second layer (note the indices)
pp <- gtable_add_grob(res, z$grobs[[locations[3]]]$grobs[[1]], 1, 1, 1, 3) %>%
gtable_add_grob(zz, ., t = top, l = l[2], b = top, r = r[2], name = c("add-strip"))
# Plotting
grid.newpage()
print(grid.draw(pp))
Cảm ơn rất nhiều cho các giải pháp. Tôi đã đấu tranh để tìm cách làm thế nào để khái quát hóa giải pháp này để sửa đổi các nhãn khía cạnh nếu chúng xảy ra ở bên phải của cốt truyện.Bạn có thể chỉ ra cách người ta sửa đổi giải pháp của bạn thành bộ trường hợp bố trí dựa trên hàm lô ggplot (cbind (df, df), aes (x = x, y = y)) + geom_point() + facet_grid (f1 + f2 ~ f3) '? Tôi tiếp tục cần phải khái quát hóa một trường hợp với 12 hàng khía cạnh giảm xuống 6 nhãn bên ngoài bên phải thay vì 4 và 2 (như hàm viết lại mà tôi đã cung cấp sẽ tạo ra). Vui lòng cung cấp một ví dụ rõ ràng nếu điều đó có ích. Cảm ơn nhiều! – nickb