Resize strip.background to match strip.text in ggplot facet_wrap

I am trying to do a lot of "small multiples" plots.

(Secondary / Background) I have too many faces to display in one graph, so I need to adjust them manually for separate plots. I was hoping that I could simply pass the desired ncol

and nrow

in facet_wrap

, and he would do as much as I need. This is beside the point.

Since I have so many facets, space is at its best. So, I wanted to reduce the size of the facet labels. It is easy enough to reduce the font size strip.text

, but unfortunately the rectangle strip.background

does not have a font size and does not provide sizing options (other than the border size). Setting it to element_blank()

doesn't actually remove the space allocated to it, it just makes the same space transparent.

MWE:

set.seed(1)
xcat = rep(1:10, 1000)
yvalue1 = rep(runif(10,5,7),1000)
yvalue2 = rep(runif(10,4,6),1000)
id = rep(1:1000,each=10)

df = data.frame(id,xcat,yvalue1,yvalue2)

for(i in seq(1, length(unique(df$id)), by=100)){
  print(
    ggplot(subset(df, id %in% unique(df$id)[i:(i+99)]), aes(x=xcat)) +
      annotate("line", y=yvalue1, x=xcat, colour="cornflowerblue") + 
      annotate("line", y=yvalue2, x=xcat, colour="grey20") + 
      theme(axis.text.x = element_text(size=5),
            axis.text.y = element_text(size=5),
            strip.text = element_text(size=5)) +
      facet_wrap(~id, ncol=10, nrow=10) + 
      expand_limits(y=0))
}

      

example image with default gray strip.background

Any ideas on how I could reduce the height of this strip.background so that it doesn't take up that much space? Ideally it will be the exact height of the id text.

As a bonus, how to reduce the distance between the edges? (Is there a parameter in facet_wrap I'm missing?)

It also takes a REALLY long time with RStudio facet_wrap

(without facet_wrap it's much faster.

+3


source to share


1 answer


The result you want can be modified by modifying the grobs

created one ggplot

. This process is somewhat confusing and required for manual configuration:

Leaving aside a loop that doesn't affect the problem, we can start by decreasing the distance between the faces. This can be easily done by adding an argument panel.spacing

to theme

.

library(ggplot2)

d <- ggplot(subset(df, id %in% unique(df$id)[1:(100)]), aes(x=xcat)) +
  annotate("line", y=yvalue1, x=xcat, colour="cornflowerblue") + 
  annotate("line", y=yvalue2, x=xcat, colour="grey20") + 
  theme(axis.text.x = element_text(size=5),
        axis.text.y = element_text(size=5),
        strip.text = element_text(size=5),
        panel.spacing = unit(.5, 'pt')) +
  facet_wrap(~id, ncol=10, nrow=10) +
  expand_limits(y=0)

      

Then we need to generate ggplot2 plot grob. This will create a list of the individual elements that make up the plot.

g <- ggplotGrob(d)

head(g, 5)
# TableGrob (5 x 43) "layout": 13 grobs
#    z         cells        name                                    grob
# 1  3 ( 5- 5, 4- 4)  axis-t-1-1                          zeroGrob[NULL]
# 2  3 ( 5- 5, 8- 8)  axis-t-2-1                          zeroGrob[NULL]
# 3  3 ( 5- 5,12-12)  axis-t-3-1                          zeroGrob[NULL]
# 4  3 ( 5- 5,16-16)  axis-t-4-1                          zeroGrob[NULL]
# 5  3 ( 5- 5,20-20)  axis-t-5-1                          zeroGrob[NULL]
# 6  3 ( 5- 5,24-24)  axis-t-6-1                          zeroGrob[NULL]
# 7  3 ( 5- 5,28-28)  axis-t-7-1                          zeroGrob[NULL]
# 8  3 ( 5- 5,32-32)  axis-t-8-1                          zeroGrob[NULL]
# 9  3 ( 5- 5,36-36)  axis-t-9-1                          zeroGrob[NULL]
# 10 3 ( 5- 5,40-40) axis-t-10-1                          zeroGrob[NULL]
# 11 4 ( 4- 4, 4-40)      xlab-t                          zeroGrob[NULL]
# 12 8 ( 3- 3, 4-40)    subtitle zeroGrob[plot.subtitle..zeroGrob.77669]
# 13 9 ( 2- 2, 4-40)       title    zeroGrob[plot.title..zeroGrob.77668]

      

Our goal is to find and fix the height in relation to the stripes.

for(i in 1:length(g$grobs)) {
  if(g$grobs[[i]]$name == 'strip') g$grobs[[i]]$heights <- unit(5, 'points')
}

      



Unfortunately, strip

grobs

different heights

main section is affected , which is divided into, so we have to reduce that as well. I haven't found a way to identify programmatically which heights are g$heights

relative to the strip, but checking is pretty quick to figure out what we need.

g$heights
# [1] 5.5pt               0cm                 0cm                 0cm                 0cm                
# [6] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [11] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [16] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [21] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [26] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [31] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [36] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [41] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [46] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [51] 0.518897450532725cm 1null               0.306264269406393cm 1grobheight         0cm                
# [56] 5.5pt       

strip_grob_position <- seq(6, length(g$heights) - 5, 5)
for(i in strip_grob_position) {
  g$heights[[i]] = unit(.05, 'cm')
}

      

Finally, we can do the result:

library(grid)
grid.newpage()
grid.draw(g)

      

enter image description here

I am not an expert at all in the topic, so I could say or explain something incorrectly or inaccurately. Also, there may be better (and simpler and more ggplot-ish) ways to get the result.

+1


source







All Articles