To get the strips to span the columns, you will probably need to use gtable
functions (and a couple of grid
functions).
In the solution, rows are added to the chart's gtable, then the strips are added to the new rows. The strips could be constructed from scratch, but it's probably easier to draw a second chart with the strip oriented horizontally, then extract the strips.
(Note: This could easily break with the next ggplot version.)
library(ggplot2)
library(dplyr)
mydata = tribble(
~x, ~y, ~data, ~more,
0, 50, 'iris', 'this',
10, 100, 'iris', 'this',
0, 50, 'iris', 'that',
10, 100, 'iris', 'that',
0, 0, 'wine', 'this',
10, 10, 'wine', 'this',
0, 0, 'wine', 'that',
10, 10, 'wine', 'that',
)
### Construct two charts:
# 1. ToKeep - the data~more chart, but without the strip labels.
# The strips across the tops of the two rows of panels will be added later.
(ToKeep <- ggplot(mydata, aes(x,y)) +
facet_grid(data ~ more, scale ='free') +
geom_point() +
theme(strip.text.y = element_blank(),
strip.text.x= element_blank()) )
# 2. ToGetStrip - Get the strips from the more~data chart
ToGetStrip <- ggplot(mydata, aes(x,y)) +
facet_grid(more ~ data, scale = 'free') +
geom_point()
# Get the ggplot grob
gt = ggplotGrob(ToGetStrip)
# Get the strips
library(gtable)
library(grid)
strip = gtable_filter(grid.force(gt), "strip-t")
# Make sure
grid.newpage()
grid.draw(strip$grobs[[1]])
grid.newpage()
grid.draw(strip$grobs[[2]])
## Add the strips to the ToKeep chart.
# Get ggplot grob
gt = ggplotGrob(ToKeep)
# Check heights and widths
gt$heights
gt$widths
# The 1null heights and widths are the panels' heights and widths.
# Add rows to the gtable immediately above the panel rows (that is, after row 9 then row 7).
# The height of the new rows is the height of the strip grobs.
gt <- gtable_add_rows(gt, height = strip$grobs[[1]]$height, pos = 9)
gt <- gtable_add_rows(gt, height = strip$grobs[[1]]$height, pos = 7)
# Add the strips to the new rows ( t = c(8, 11) )
# and make sure they span the two columns of panels ( l = 5, r = 7 )
gt <- gtable_add_grob(gt, list(strip$grobs[[1]], strip$grobs[[2]]), t = c(8, 11), l = 5, r = 7)
# Draw it
grid.newpage()
grid.draw(gt)

Following is an attempt to select rows and columns in terms of panel positions. However, it has not been tested beyond your 2 X 2 chart. (This could be a little more resilient to changes to ggplot.)
# Construct the two charts
ToKeep <- ggplot(mydata, aes(x,y)) +
facet_grid(data ~ more, scale ='free') +
geom_point() +
theme(strip.text.y = element_blank(),
strip.text.x= element_blank())
ToGetStrip <- ggplot(mydata, aes(x,y)) +
facet_grid(more ~ data, scale = 'free') +
geom_point()
# Get the strips from the second chart
gt = ggplotGrob(ToGetStrip)
library(grid)
library(gtable)
strip = gtable_filter(grid.force(gt), "strip-t")
# Add rows to the ToKeep chart, and add the strips to the new rows
gt = ggplotGrob(ToKeep)
PanelPos = subset(gt$layout, grepl("panel", gt$layout$name), select = t:r)
PanelRows = rev(unique(PanelPos$t))
for(i in seq_along(PanelRows)) {
gt <- gtable_add_rows(gt, height = strip$grobs[[1]]$height, pos = PanelRows[i]-1)
}
PanelRows = unique(subset(gt$layout, grepl("panel", gt$layout$name), select = t, drop = TRUE))
gt <- gtable_add_grob(gt, strip$grobs, t = PanelRows - 1, l = min(PanelPos$l), r = max(PanelPos$r))
# Draw it
grid.newpage()
grid.draw(gt)