113 votes

aligner à gauche deux bords du graphique (ggplot)

Je suis en utilisant ggplot et ont deux graphiques que je veux afficher sur le dessus les uns des autres. J'ai utilisé grid.arrange de gridExtra de les empiler. Le problème c'est que je veux le bord gauche des graphiques pour aligner ainsi que les bords droits, indépendamment des étiquettes de l'axe. (le problème se pose parce que les étiquettes d'un graphe sont courts tandis que l'autre est long).

La Question:
Comment puis-je faire cela? Je ne suis pas marié à la grille.organiser des mais le ggplot2 est un must.

Ce que j'ai essayé:
J'ai essayé de jouer avec la largeur et la hauteur ainsi que ncol et nrow à faire une 2 x 2 grille et placez les visuels dans les coins opposés et jouer avec les largeurs, mais je ne pouvais pas obtenir les visuels dans les coins opposés.

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)

enter image description here

150voto

baptiste Points 19677

Essaye ça,

  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)
 

modifier

Voici une solution alternative utilisant une version modifiée de gtable:::rbind_gtable et cbind_gtable , pour un nombre arbitraire de parcelles.

 rbind_gtable_max <- function(...){

  gtl <- list(...)
  stopifnot(all(sapply(gtl, is.gtable)))
  bind2 <- function (x, y) 
  {
    stopifnot(ncol(x) == ncol(y))
    if (nrow(x) == 0) 
      return(y)
    if (nrow(y) == 0) 
      return(x)
    y$layout$t <- y$layout$t + nrow(x)
    y$layout$b <- y$layout$b + nrow(x)
    x$layout <- rbind(x$layout, y$layout)
    x$heights <- gtable:::insert.unit(x$heights, y$heights)
    x$rownames <- c(x$rownames, y$rownames)
    x$widths <- grid::unit.pmax(x$widths, y$widths)
    x$grobs <- append(x$grobs, y$grobs)
    x
  }

  Reduce(bind2, gtl)
}

cbind_gtable_max <- function(...){

  gtl <- list(...)
  stopifnot(all(sapply(gtl, is.gtable)))
  bind2 <- function (x, y) 
  {
    stopifnot(nrow(x) == nrow(y))
    if (ncol(x) == 0) 
      return(y)
    if (ncol(y) == 0) 
      return(x)
    y$layout$l <- y$layout$l + ncol(x)
    y$layout$r <- y$layout$r + ncol(x)
    x$layout <- rbind(x$layout, y$layout)
    x$widths <- gtable:::insert.unit(x$widths, y$widths)
    x$colnames <- c(x$colnames, y$colnames)
    x$heights <- grid::unit.pmax(x$heights, y$heights)
    x$grobs <- append(x$grobs, y$grobs)
    x
  }
  Reduce(bind2, gtl)
}

grid.draw(rbind_gtable_max(gA, gB))
 

(notez que la modification n'est nécessaire que parce que gtable ne parvient pas à comparer certains types d'unités composées avec unit.pmax )

41voto

slizb Points 153

Je voulais généraliser cela pour n'importe quel nombre de parcelles. Voici une solution étape par étape utilisant l'approche de Baptiste:

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

collecter les largeurs pour chaque graob de chaque parcelle

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

utilisez do.call pour obtenir la largeur maximale

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

assigne la largeur maximale à chaque grob

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

terrain

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

12voto

Wilbert Points 31

Sur http://rpubs.com/MarkusLoew/13295 est une solution vraiment facile disponible (dernier élément) Appliquée à ce problème:

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

vous pouvez également l'utiliser pour la largeur et la hauteur:

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

8voto

bdemarest Points 5495

Voici une autre solution possible utilisant melt du paquet reshape2 et 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)
 

entrez la description de l'image ici

0voto

Tyler Rinker Points 27607

Au mieux, c'est un hack:

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

Cela semble vraiment faux.

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