4
votes

I would like to automatically adjust the ggplot graphs while plotting side-by-side.

library(ggplot2)
library(gridExtra)

set.seed(123)
freq <- sample(1:10, 7, replace = T)
labels <- c('AUS', 'NZ', 'ENG', 'SOC', 'PAK', 'SRI', 'IND')
value <- paste("i",1:10,sep='')

lab <- rep(unlist(lapply(1:length(freq), function(x) rep(labels[x],freq[x]))),2)
ival <- rep(unlist(lapply(1:length(freq), function(x) value[1:freq[x]])),2)

df <- data.frame(lab, ival, type=c(rep('Type1',42),rep('Type2',42)),val=runif(84,0,1))

Plotting the data generated using the random process above.

plotUng <- ggplot(df, aes(x=ival, y=val, col = type, group = type)) + 
  geom_line() + 
  geom_point(aes(x=ival, y=val)) +
  facet_wrap( ~lab, ncol=3) + 
  theme(axis.text.x=element_text(angle=45, vjust=0.3)) + 
  scale_x_discrete(limits=paste('i',1:10,sep=''))

Now grouping the data in lab based on some condition. Now I would like to generate new plot based on the grouped data.

dfGrp <- df %>% mutate(lab = recode(lab, 'AUS' = 'A', 'NZ' = 'A', 'ENG' = 'A', 
                                    'SOC' = 'A', 'PAK' = 'B', 'SRI' = 'B')) %>% 
  group_by(lab, ival, type) %>% mutate(val = mean(val)-0.2) %>% ungroup() %>% distinct()

plotG <- ggplot(dfGrp, aes(x=ival, y=val, col = type, group = type)) + 
  geom_line() + 
  geom_point(aes(x=ival, y=val)) +
  facet_wrap( ~lab, ncol=3) + 
  theme(axis.text.x=element_text(angle=45, vjust=0.3)) + 
  scale_x_discrete(limits=paste('i',1:10,sep=''))

Plotting the above two plots side-by-side for comparison using grid.arrange.

grid.arrange(plotUng, plotG, ncol=2)

enter image description here

Adjusting the y-axis limits after manual inspection of the above plot that plotUng has wider limits than plotG. So, adjusted the limits of plotG with the limits of plotUng as coord_cartesian(ylim = ggplot_build(plotUng)$layout$panel_ranges[[1]]$y.range).

grid.arrange(plotUng, plotG + coord_cartesian(ylim = ggplot_build(plotUng)$layout$panel_ranges[[1]]$y.range), ncol=2)

enter image description here

The above plot is as expected. Is there any way to do this automatically(just with the plot objects) without manual inspection, as it is not always possible to manually inspect all the plots and adjust the axis limits accordingly?

1
Were you able to get addressed? I'm looking for a similar way to do this too. I am looking to expand the y axis only for certain graphs (where a value is greater than 100 for example), but the rest of the graphs would be a max y axis of 75. - Scott R
@ScottR Nope, I haven't found an automated way. If you find a better way, please share it with me. Thanks! - Prradep
I went ahead and posted my question about this. It's not quite the same as yours, but hopefully could offer some inspiration of sorts. stackoverflow.com/questions/66335729/… - Scott R

1 Answers

2
votes

What you did with ggplot_build() can be automated. But for me the simplest way to compare several plots is to find the minimum and maximum values for all objects to be compared, and then put these values as coord_cartesian() of every objects. For example here :

lim_y <- c( min(df$val, dfGrp$val), max(df$val, dfGrp$val) )

plotUng <- plotUng + coord_cartesian(ylim = lim_y)
plotG <- plotG + coord_cartesian(ylim = lim_y)

grid.arrange(plotUng, plotG, ncol=2)

enter image description here

Since finding the extreme values of several columns is straightforward, this is the most "automated" way I've found.

Note that the coordinate problems only happens for y-limits in ggplot