1

I want to generate an output of x plots with ggplot on differennt pages. The y labels are text variables with different lengths. Depending on the max. length of these labels the plots are not looking the same, label and diagram area are automatically optimized by ggplot. There should be a way to have always the same width for the y labels or not? page 1

page 2

Code fragment of ggplot command:

print(ggplot(dfPriceArt[ixStart:ixEnde, ], aes(x=reorder(BATArtikelKomplett, MaxEinzelpreisPerc), y=MaxEinzelpreisPerc, size=MaxEinzelpreisPerc)) + 
geom_point() +
coord_flip() +
labs(y='BATArtikel',x='MaxEinzelpreis') +
theme(axis.text=element_text(size=6)) +
scale_y_continuous(limits=c(100, maxEinzelpreisPerc)) +
scale_size_continuous(limits=c(100, maxEinzelpreisPerc)))
Juppes
  • 169
  • 9
  • 1
    Possible duplicate of [left align two graph edges (ggplot)](https://stackoverflow.com/questions/13294952/left-align-two-graph-edges-ggplot) – Thomas K Apr 20 '18 at 07:50
  • @ThomasK as I understand the OP wants the plots on two pages. Thus it seems not to be a dupe. At least not the linked. Nevertheless reproducible example data should be included. – Roman Apr 20 '18 at 08:19
  • @Jimbou you are correct. It didn't occur to me, that you'd want to align plots when not plotting them next to each other, but there might be some use case for it. In this case I would recommend to pad the labels and use a fixed width font, similar to here: https://stackoverflow.com/questions/48533942/ggplot2-yaxis-labels-not-aligning-across-facets – Thomas K Apr 20 '18 at 08:34

3 Answers3

2

you can try

library(tidyverse)
library(grid)
library(gridExtra)
# some data and plots
df <-  iris %>% 
  bind_rows(iris %>% mutate(Species=paste0(Species,"_", Species)), .id = "gr") %>% 
  group_by(gr,Species) %>% 
  summarise(y=mean(Sepal.Length)) %>% 
  nest(-gr) %>%   
  mutate(plots= map(data, ~ggplot(data=.x, aes(Species, y)) +
               geom_point() +
               coord_flip()))

df$plots
[[1]]

[[2]]

enter image description here enter image description here

# updating the width
gp1<- ggplot_gtable(ggplot_build(df$plots[[1]]))
gp2<- ggplot_gtable(ggplot_build( df$plots[[2]]))
maxWidth = unit.pmax(gp1$widths[2:3], gp2$widths[2:3])

gp1$widths[2:3] <- maxWidth
gp2$widths[2:3] <- maxWidth
grid.arrange(gp1)

enter image description here^

grid.arrange(gp2)

enter image description here

Finally you can save the plots using

ggsave("test1.jpeg",grid.arrange(gp1))
ggsave("test2.jpeg",grid.arrange(gp2))

The idea was

Roman
  • 17,008
  • 3
  • 36
  • 49
1

The first comment to left align two graph edges (ggplot) helped a lot to find an own solution additionally with Align multiple plots in ggplot2 when some have legends and others don't (last edit).

As @Jimbou pointed out I wanted to have one plot per page, sorry to have not mentioned that.

This is what my solution now looks like:

library(gridExtra)
...
for (i in 1:iLast) {
    ...
    p <- ggplot(dfPriceArt[ixStart:ixEnde, ], aes(x=reorder(BATArtikelKomplett, MaxEinzelpreisPerc), y=MaxEinzelpreisPerc, size=MaxEinzelpreisPerc)) + 
        geom_point() +
        coord_flip() +
        labs(y='BATArtikel',x='MaxEinzelpreis') +
        theme(axis.text=element_text(size=6)) +
        scale_y_continuous(limits=c(100, maxEinzelpreisPerc)) +
        scale_size_continuous(limits=c(100, maxEinzelpreisPerc))
    plot_list[[i]] <- ggplotGrob(p)
    widths_list[[i]] <- plot_list[[i]]$widths[2:5]
    ...
}
maxWidth <- do.call(grid::unit.pmax, widths_list)
for (i in 1:iLast) {
  plot_list[[i]]$widths[2:5] <- as.list(maxWidth)
  grid.draw(plot_list[[i]])
  if (i != iLast) {
    grid.newpage()
  }
}
Juppes
  • 169
  • 9
0

There is no direct way I know of, but you can pad the y-labels and use a fixed width font to align the plots. Since you didn't supply any sample data, this is a short made up example:

library(tidyverse)
library(gridExtra)

# create two data.frames with differing lengths for the labels
df1 <- tribble(~x, ~y,
               1, paste0(letters[1:10], collapse = ""))

df2 <- tribble(~x, ~y,
               1, paste0(letters[1:20], collapse = ""))

# find the length of the longest label
max_length <- max(str_length(df2$y))

# pad the shorter labels
df1 <- mutate(df1, y = str_pad(y, max_length, side = "left"))


# create plots using a fixed width font
p1 <- ggplot(df1, aes(x, y)) +
  geom_point()+
  theme(axis.text.y = element_text(family = "mono"))

p2 <- ggplot(df2, aes(x, y)) +
  geom_point()+
  theme(axis.text.y = element_text(family = "mono"))

# arrange them for demonstrative purposes
grid.arrange(p1, p2)

Created on 2018-04-20 by the reprex package (v0.2.0).

Thomas K
  • 3,242
  • 15
  • 29