facet_wrap
simply puts one plot after the other and inserts "line breaks" after the appropriate number of plots. But there is also facet_grid
that lets you specify a row and a column index. Your row index is group
and I now add a column index as follows:
cols<-c(a=1,c=1,f=1,b=2,d=2,g=2,e=3)
df$col <- as.factor(cols[as.character(df$name)])
Now you can plot the facet grid with
ggplot(df, aes(x,y)) + geom_point() + facet_grid(group~col)
Of course, depending on what your problem is, you will have to think of an appropriate way to set the column indices.
This is the plot:
Edit:
In reaction to your comment and drawing from this answer, I created a second solution. It uses gridExtra
and manipulates the ggplot grob directly. I think it gives the desired result, but in the form I present it, it is "manual work". This solution uses facet_wrap
instead of facet_grid
.
First, I add a "place holder levels" to the variable name
, which will ensure that the empty facets are created and then create the plot:
df$name2 <- factor(df$name,levels=c('a','b','','c','d','e','f','g',' '))
p <- ggplot(df, aes(x,y)) + geom_point() + facet_wrap(~name2,ncol=3,drop=FALSE)
drop=FALSE
is what causes ggplot
to draw the empty facets.
This plot differs from my first solution only in how the facets are labelled. Now to the tricky part:
library(gridExtra)
g <- ggplotGrob(p)
## remove empty panels
g$grobs[names(g$grobs) %in% c("panel3", "panel9", "strip_t3", "strip_t9")] <- NULL
## remove them from the layout
g$layout <- g$layout[!(g$layout$name %in% c("panel-3", "panel-9",
"strip_t-3", "strip_t-9")),]
## move axis closer to panel
g$layout[g$layout$name == "axis_b-9", c("t", "b")] = c(9,9)
This does basically what the comments say. If you work with another set of plots, look at the output of names(g$grobs)
and g$layout$name
to figure out, which elements have to be removed.
Now you can create the plot with
grid.newpage()
grid.draw(g)
Edit 2:
For newer versions of ggplot2
the above solution does not work. Unfortunately, I don't know with which version this started, but it definitely does not work with version 2.2.1.
The part that must be changed is the modification of the grob:
g <- ggplotGrob(p)
# get the grobs that must be removed
rm_grobs <- g$layout$name %in% c("panel-1-3", "panel-3-3", "strip-t-3-1", "strip-t-3-3")
# remove grobs
g$grobs[rm_grobs] <- NULL
g$layout <- g$layout[!rm_grobs, ]
## move axis closer to panel
g$layout[g$layout$name == "axis-b-3-3", c("t", "b")] = c(14.5, 14.5)
grid.newpage()
grid.draw(g)
The main changes are that g$grobs
is no longer a named list and that the names of the grobs have changed. Note the panels are labelled as "panel-row-col"
while for grey bars it is "strip-t-col-row"
.