93 votes

Comment puis-je organiser un nombre arbitraire de ggplots à l'aide de la grille.organiser?

C'est cross-posté sur le ggplot2 groupe google

Ma situation est que je suis de travailler sur une fonction qui génère un nombre arbitraire de parcelles (selon les données fournies par l'utilisateur). La fonction retourne une liste de n parcelles, et je voudrais proposer ces parcelles à 2 x 2 formation. Je suis aux prises avec les problèmes simultanés de:

  1. Comment puis-je permettre la souplesse nécessaire pour être remis à un arbitraire (n) nombre de parcelles?
  2. Comment puis-je aussi préciser que je veux les énoncés 2 x 2

Ma stratégie actuelle utilise grid.arrange de la gridExtra package. Ce n'est probablement pas optimale, surtout depuis que, et cela est essentiel, totalement ne fonctionne pas. Voici mon commenté exemple de code, d'expérimenter avec les trois parcelles:

library(ggplot2)
library(gridExtra)

x <- qplot(mpg, disp, data = mtcars)
y <- qplot(hp, wt, data = mtcars)
z <- qplot(qsec, wt, data = mtcars)

# A normal, plain-jane call to grid.arrange is fine for displaying all my plots
grid.arrange(x, y, z)

# But, for my purposes, I need a 2 x 2 layout. So the command below works acceptably.
grid.arrange(x, y, z, nrow = 2, ncol = 2)

# The problem is that the function I'm developing outputs a LIST of an arbitrary
# number plots, and I'd like to be able to plot every plot in the list on a 2 x 2
# laid-out page. I can at least plot a list of plots by constructing a do.call()
# expression, below. (Note: it totally even surprises me that this do.call expression
# DOES work. I'm astounded.)
plot.list <- list(x, y, z)
do.call(grid.arrange, plot.list)

# But now I need 2 x 2 pages. No problem, right? Since do.call() is taking a list of
# arguments, I'll just add my grid.layout arguments to the list. Since grid.arrange is
# supposed to pass layout arguments along to grid.layout anyway, this should work.
args.list <- c(plot.list, "nrow = 2", "ncol = 2")

# Except that the line below is going to fail, producing an "input must be grobs!"
# error
do.call(grid.arrange, args.list)

Comme je suis l'habitude de le faire, je demande humblement se blottir dans le coin, attendant impatiemment le sagace commentaires d'une communauté beaucoup plus sage que moi et Surtout si je suis en train de faire ce plus difficile qu'il doit être.

45voto

JD Long Points 20477

Vous y êtes PRESQUE! Le problème est qu' do.call attend vos arguments pour être dans un nommé list objet. Vous les ai mis dans la liste, mais comme des chaînes de caractères, qui ne sont pas nommées les éléments de la liste.

Je pense que cela devrait fonctionner:

args.list <- c(plot.list, 2,2)
names(args.list) <- c("x", "y", "z", "nrow", "ncol")

Ben Josué l'a souligné dans les commentaires, j'ai pu avoir attribué des noms quand j'ai créé la liste:

args.list <- c(plot.list,list(nrow=2,ncol=2))

ou

args.list <- list(x=x, y=y, z=x, nrow=2, ncol=2)

16voto

baptiste Points 19677

Essayez ceci,

require(ggplot2)
require(gridExtra)
plots <- lapply(1:11, function(.x) qplot(1:10,rnorm(10), main=paste("plot",.x)))

params <- list(nrow=2, ncol=2)

n <- with(params, nrow*ncol)
## add one page if division is not complete
pages <- length(plots) %/% n + as.logical(length(plots) %% n)

groups <- split(seq_along(plots), 
  gl(pages, n, length(plots)))

pl <-
  lapply(names(groups), function(g)
         {
           do.call(arrangeGrob, c(plots[groups[[g]]], params, 
                                  list(main=paste("page", g, "of", pages))))
         })

class(pl) <- c("arrangelist", "ggplot", class(pl))
print.arrangelist = function(x, ...) lapply(x, function(.x) {
  if(dev.interactive()) dev.new() else grid.newpage()
   grid.draw(.x)
   }, ...)

## interactive use; open new devices
pl

## non-interactive use, multipage pdf
ggsave("multipage.pdf", pl)

4voto

Hendy Points 1608

Je vais répondre un peu en retard, mais suis tombé sur une solution à la R Graphique livre de cuisine qui fait quelque chose de très similaire à l'aide d'une fonction personnalisée appelée multiplot. Peut-être que cela aidera d'autres personnes qui trouvent cette question. Je suis aussi d'ajouter de la réponse que la solution peut être plus récente que les autres réponses à cette question.

Plusieurs graphiques sur une page (ggplot2)

Voici la fonction en cours, mais s'il vous plaît utiliser le lien ci-dessus, que l'auteur a noté qu'il a été mis à jour pour ggplot2 0.9.3, ce qui indique qu'il peut encore changer.

# Multiple plot function
#
# ggplot objects can be passed in ..., or to plotlist (as a list of ggplot objects)
# - cols:   Number of columns in layout
# - layout: A matrix specifying the layout. If present, 'cols' is ignored.
#
# If the layout is something like matrix(c(1,2,3,3), nrow=2, byrow=TRUE),
# then plot 1 will go in the upper left, 2 will go in the upper right, and
# 3 will go all the way across the bottom.
#
multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) {
  require(grid)

  # Make a list from the ... arguments and plotlist
  plots <- c(list(...), plotlist)

  numPlots = length(plots)

  # If layout is NULL, then use 'cols' to determine layout
  if (is.null(layout)) {
    # Make the panel
    # ncol: Number of columns of plots
    # nrow: Number of rows needed, calculated from # of cols
    layout <- matrix(seq(1, cols * ceiling(numPlots/cols)),
                    ncol = cols, nrow = ceiling(numPlots/cols))
  }

 if (numPlots==1) {
    print(plots[[1]])

  } else {
    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout))))

    # Make each plot, in the correct location
    for (i in 1:numPlots) {
      # Get the i,j matrix positions of the regions that contain this subplot
      matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE))

      print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
                                      layout.pos.col = matchidx$col))
    }
  }
}

On crée de la parcelle objets:

p1 <- ggplot(...)
p2 <- ggplot(...)
# etc.

Et puis les transmet à multiplot:

multiplot(p1, p2, ..., cols = n)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X