Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to position strip labels in facet_wrap like in facet_grid

Tags:

r

ggplot2

I would like to remove the redundancy of strip labels when using facet_wrap() and faceting with two variables and both scales free.

For example, this facet_wrap version of the following graph

library(ggplot2)
dt <- txhousing[txhousing$year %in% 2000:2002 & txhousing$month %in% 1:3,]

ggplot(dt, aes(median, sales)) +
  geom_point() +
  facet_wrap(c("year", "month"), 
             labeller = "label_both", 
             scales = "free")

facet_wrap_version

should have the looks of this facet_grid version of it, where the strip labels are at the top and right edge of the graph (could be bottom and left edge as well).

ggplot(dt, aes(median, sales)) +
  geom_point() +
  facet_grid(c("year", "month"), 
             labeller = "label_both", 
             scales = "free")

enter image description here

Unfortunately, using facet_grid is not an option because, as far as I understand, it doesn't allow scales to be "completely free" - see here or here

One attempt that I thought about would be to produce separate plots and then combine them:

library(cowplot)
theme_set(theme_gray()) 

p1 <- ggplot(dt[dt$year == 2000,], aes(median, sales)) +
  geom_point() +
  facet_wrap("month", scales = "free") +
  labs(y = "2000") + 
  theme(axis.title.x = element_blank())

p2 <- ggplot(dt[dt$year == 2001,], aes(median, sales)) +
  geom_point() +
  facet_wrap("month", scales = "free") +
  labs(y = "2001") + 
  theme(strip.background = element_blank(),
        strip.text.x = element_blank(),
        axis.title.x = element_blank())

p3 <- ggplot(dt[dt$year == 2002,], aes(median, sales)) +
  geom_point() +
  facet_wrap("month", scales = "free") +
  labs(y = "2002") + 
  theme(strip.background = element_blank(),
        strip.text.x = element_blank())

plot_grid(p1, p2, p3, nrow = 3)

enter image description here

I am ok with the above hackish attempt, but I wonder if there is something in facet_wrap that could allow the desired output. I feel that I miss something obvious about it and maybe my search for an answer didn't include the proper key words (I have the feeling that this question was addressed before).

like image 342
Valentin Avatar asked Oct 08 '18 16:10

Valentin


People also ask

What is the difference between Facet_wrap and Facet_grid?

The facet_grid() function will produce a grid of plots for each combination of variables that you specify, even if some plots are empty. The facet_wrap() function will only produce plots for the combinations of variables that have values, which means it won't produce any empty plots.

What is the function of Facet_grid () in Ggplot ()?

facet_grid() forms a matrix of panels defined by row and column faceting variables. It is most useful when you have two discrete variables, and all combinations of the variables exist in the data.

How do you remove facet labels?

Facet labelsSetting strip. text to element_blank() will remove all facet labels. You can also remove the labels across rows only with strip.

What does Facet_wrap do in Ggplot?

facet_wrap() makes a long ribbon of panels (generated by any number of variables) and wraps it into 2d. This is useful if you have a single variable with many levels and want to arrange the plots in a more space efficient manner.


1 Answers

This does not seem easy, but one way is to use grid graphics to insert panel strips from a facet_grid plot into one created as a facet_wrap. Something like this:

First lets create two plots using facet_grid and facet_wrap.

dt <- txhousing[txhousing$year %in% 2000:2002 & txhousing$month %in% 1:3,]

g1 = ggplot(dt, aes(median, sales)) +
  geom_point() +
  facet_wrap(c("year", "month"), scales = "free") +
  theme(strip.background = element_blank(),
        strip.text = element_blank())

g2 = ggplot(dt, aes(median, sales)) +
  geom_point() +
  facet_grid(c("year", "month"), scales = "free")

Now we can fairly easily replace the top facet strips of g1 with those from g2

library(grid)
library(gtable) 
gt1 = ggplot_gtable(ggplot_build(g1))
gt2 = ggplot_gtable(ggplot_build(g2))
gt1$grobs[grep('strip-t.+1$', gt1$layout$name)] = gt2$grobs[grep('strip-t', gt2$layout$name)]
grid.draw(gt1)

enter image description here

Adding the right hand panel strips need us to first add a new column in the grid layout, then paste the relevant strip grobs into it:

gt.side1 = gtable_filter(gt2, 'strip-r-1')
gt.side2 = gtable_filter(gt2, 'strip-r-2')
gt.side3 = gtable_filter(gt2, 'strip-r-3')

gt1 = gtable_add_cols(gt1, widths=gt.side1$widths[1], pos = -1)
gt1 = gtable_add_grob(gt1, zeroGrob(), t = 1, l = ncol(gt1), b=nrow(gt1))

panel_id <- gt1$layout[grep('panel-.+1$', gt1$layout$name),]
gt1 = gtable_add_grob(gt1, gt.side1, t = panel_id$t[1], l = ncol(gt1))
gt1 = gtable_add_grob(gt1, gt.side2, t = panel_id$t[2], l = ncol(gt1))
gt1 = gtable_add_grob(gt1, gt.side3, t = panel_id$t[3], l = ncol(gt1))

grid.newpage()
grid.draw(gt1)

enter image description here

like image 192
dww Avatar answered Nov 15 '22 21:11

dww