It is often convenient to use ggplot's facet_grid
or facet_panel
for creating subplots, rather than using alternative packages such as grid/cowplot. However, I find that customizing specific thematic properties of individual facets to be an elusive process. Many have posed the question about modifying the axis scales, and there are solutions abound.
However, I'd like to know how one can have fine control over the theme parameters of individual panel axes. For example, let's say I want to set the tick-mark labels of panel x to be transparent or have a font size different from that of other panels.
Although my immediate issue is concerned with eliminating the tick labels (while retaining the y-axis line and tick marks, hence scales = free
), I'd be interested in a more generalized solution to controlling the theme elements of specific panels when using facet_grid
or facet_wrap
. Specifically, I'm wondering if there is anyway to modify specific theme attributes, particularly of axes, of individual panels without using things like gtable/grobs, etc.
With respect to the problem at hand, here's my attempt at implementing a hack to 'erase' the tick labels for subplots on the right, but it appears that the the axis text layer is given precedence over geoms and so is not covered. In practice, the fill colour would be white, but I've made it black here for illustrative purposes.
library(egg)
library(ggplot2)
df.rect <- data.frame(Species = c("setosa", "versicolor", "virginica"),
xmin = c(4.60,4.60,NA),
xmax = c(4.89,4.89,NA),
ymin = c(-0.05,-0.05,NA),
ymax = c(1.55,1.55,NA))
p1 <- ggplot(data = iris, aes(x = Sepal.Width, fill = Species)) +
facet_wrap(. ~Species, scales = "free", ncol = 4) +
geom_density(alpha = 0.30) +
theme_classic() +
labs(x = "Sepal Length", y = "Density", fill = "Species") +
coord_cartesian(xlim = c(1.95,4.45), ylim = c(-0.05,1.55), clip = "off") +
scale_x_continuous(breaks = seq(2,4.4,0.6)) +
scale_y_continuous(breaks = seq(0,1.5,0.30)) +
theme(legend.title = element_text(size = 9),
legend.text = element_text(size = 9),
legend.title.align = 0,
strip.background = element_blank(),
strip.text = element_blank(),
axis.title.x = element_text(margin = unit(c(3,0,0,0), "mm"), size = 10),
axis.title.y = element_text(margin = unit(c(0,3,0,0), "mm"), size = 10),
panel.spacing.x = unit(4, "mm"))
p1 <- tag_facet(p1)
p1 <- p1 + geom_rect(data = df.rect, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), color = "white", fill = "black", inherit.aes = FALSE)
p1
I don't think you can control theme elements on a per panel basis. The thing that you'd probably require for this is to (1) have axis guides with customisable theme elements independent of the global theme and (2) a way to set the axis guides for every panel individually. As far as I know, (2) does exist, but (1) doesn't.
With regards to your specific question, there are two packages I know of that can remove the labels at inner panels. Below are examples of both and both refuse to remove labels if the scales are free. The {lemon} package has a dedicated facet function for this:
library(ggplot2)
g <- ggplot(data = iris, aes(x = Sepal.Width, fill = Species)) +
geom_density(alpha = 0.30) +
theme_classic()
library(lemon)
#>
#> Attaching package: 'lemon'
#> The following objects are masked from 'package:ggplot2':
#>
#> CoordCartesian, element_render
g + facet_rep_wrap(~ Species, ncol = 4)
The {ggh4x} package has optional arguments that support this.
library(ggh4x)
#>
#> Attaching package: 'ggh4x'
#> The following objects are masked from 'package:lemon':
#>
#> geom_pointpath, GeomPointPath
g + facet_wrap2(~ Species, ncol = 4,
axes = "full", remove_labels = "all")
Created on 2021-08-03 by the reprex package (v2.0.0)
Disclaimer: I'm the author of ggh4x.