Упорядочить n ggplots в форме нижней треугольной матрицы
У меня есть n объектов ggplot, которые всегда будут иметь правильный номер, чтобы сделать нижний треугольник матрицы (без диагоналей). Как я могу упорядочить их в следующем порядке:
1
2 3
4 5 6
7 8 9 10
чтобы сформировать сетку (здесь n = 10)?
Вот данные, чтобы сделать n графиков и как бы я хотел, чтобы это выглядело как n = 6.
n <- sample(1:4, 1)
N <- sum(n:1)
library(ggplot2)
theplot <- ggplot(mtcars, aes(mpg, hp)) + geom_point()
plots <- lapply(1:N, function(i) theplot)
plots <- mapply(function(x, y) x + ggtitle(y), plots,
paste("PLOT", seq_along(plots)), SIMPLIFY=FALSE)
![enter image description here]()
Я подозреваю, что gridExtra
может быть полезен здесь, но есть пустые панели. Я открыт для создания или добавления идей пакетов.
Ответы
Ответ 1
Вы можете передать матричный макет в grid.arrange,
library(ggplot2)
library(gridExtra)
plots <- lapply(1:10, function(id) ggplot() + ggtitle(id))
m <- matrix(NA, 4, 4)
m[lower.tri(m, diag = T)] <- 1:10
grid.arrange(grobs = plots, layout_matrix = m)
![введите описание изображения здесь]()
Ответ 2
Здесь довольно безболезненный подход, который не следует слишком сложно обобщать:
library(gridExtra) ## for grid.arrange()
ng <- nullGrob()
grid.arrange(plots[[1]], ng, ng,
plots[[2]], plots[[3]], ng,
plots[[4]], plots[[5]], plots[[6]])
![enter image description here]()
Ответ 3
Я был поклонником wq::layOut
для размещения ggplots, когда grid.arrange
кажется слишком сложным (хотя Джош показывает, что он отлично работает здесь). Если вы используете новое устройство, вам не нужно беспокоиться о отверстиях.
layOut
был удален из пакета wq
, поэтому я включаю здесь код, переименованный в lay_out
. Он внизу, после примеров использования.
lay_out(list(plots[[1]], 1, 1), # each arg is list(plot, row(s), column(s))
list(plots[[2]], 2, 1),
list(plots[[3]], 2, 2))
![layOut1]()
Это основная сила, когда у вас разные графики.
lay_out(list(plots[[1]], 1, 1:3),
list(plots[[2]], 2, 1),
list(plots[[3]], 2, 2),
list(plots[[4]], 3, 1:2),
list(plots[[5]], 2:3, 3))
![layOut2]()
Я думаю, что все, что вы могли бы сделать с помощью layOut
, можно выполнять с помощью вложенных вызовов grid.arrange
и arrangeGrob
, но часто бывает легче подумать об этом.
#' Arranging ggplots
#'
#' Provides a \code{layout}-like interface for arranging ggplots of different
#' sizes.
#'
#' @param ... Each argument should be of the form \code{list(plot, rows,
#' columns)}, where \code{plot} is a ggplot (or similar), and \code{rows} and
#' \code{columns} are consecutive sequences indicating the row and column
#' numbers for \code{plot} to span.
#'
#' @author Alan D. Jassby and James E. Cloern (originally from the \code{wq}
#' package).
#'
#' @examples
#' \dontrun{
#' gg <- ggplot(mtcars, aes(x = hp, y = mpg)) + geom_point()
#' layOut(list(gg, 1:2, 1:3),
#' list(gg, 3, 1:2),
#' list(gg, 3, 3))
#' }
#'
#' @export
lay_out <- function(...) {
x <- list(...)
n <- max(sapply(x, function(x) max(x[[2]])))
p <- max(sapply(x, function(x) max(x[[3]])))
grid::pushViewport(grid::viewport(layout = grid::grid.layout(n, p)))
for (i in seq_len(length(x))) {
print(x[[i]][[1]],
vp = grid::viewport(layout.pos.row = x[[i]][[2]],
layout.pos.col = x[[i]][[3]]))
}
}
Ответ 4
И это более общее решение...
rows <- 1:3
get.row <- function(i){
if (i==1) return(arrangeGrob(plots[[1]],ncol=length(rows)))
start=sum(seq[1:(i-1)])+1
end <- start+seq[i]-1
do.call(arrangeGrob,c(lapply(start:end,function(i)plots[[i]]),ncol=length(rows)))
}
grid.newpage()
grid.arrange(do.call(arrangeGrob,c(lapply(1:length(rows),get.row),nrow=length(rows))))
Ответ 5
Другое обобщение, построенное на основе ответа Джоша
trianglePlotGrid <- function(plots){
#take a list of plots and returns a single plot where the elements in the list arranged in a triangular grid
#plots should be a list of 1 or 3 or 6... plots to be arranged in a trianglular structure with 1 plot in the top row
ncols <- (-1 + sqrt(1 + 8*length(plots)))/2
i = 0; j = 0
grobs <- list()
for(p in plots){
grobs[[length(grobs)+1]] <- p
j = (j+1) %% ncols
while(j > i){
grobs[[length(grobs)+1]] <- nullGrob()
j = (j+1) %% ncols
}
if(j == 0) i = i + 1
}
do.call("grid.arrange", c(grobs, ncol=ncols))
}
df <- data.frame(x=c(1,2), y=c(1,2))
p <- ggplot(df, aes(x=x, y=y))+geom_point()
plist <- list(p, p, p, p, p, p)
trianglePlotGrid(plist)
![enter image description here]()