Unfortunately, as far as I can tell (I may be wrong) the above mentioned methods cannot help you if you want to shrink the axis of a facet. For example, here is a figure from my work, with anonymized data:
In two of the facets (right column) the confidence intervals of one or two individual data points wildly shift the domain of the facet, making the general trends in the main body of data difficult to discern. I need to shrink these axes.
I've hacked together a function scale_inidividual_facet_y_axes
which very roughly accomplishes this. It's a standalone function which accepts two parameters: plot
which is the ggproto object output by ggplot functions, and ylims
which is a list of tuples, each corresponding to the y-axis for a particular facet. If you want the axis of a particular facet to remain unmodified, simply use a NULL
value for that facet's element in the ylims
list.
For example:
plot =
data %>%
ggplot(aes(...)) +
geom_thing() +
# ... construct your ggplot object as normal, and save it to a variable
geom_whatever()
ylims = list(NULL, c(-20, 100), NULL, c(0, 120))
scale_inidividual_facet_y_axes(plot, ylims = ylims)
Which produces this:
As you can see the axes of the righthand column facets have been modified, while the left hand facets remain in their original form.
This method has one immediately apparent problem: It occurs before the figures are drawn, so data which fall outside of the new axes will no longer be drawn. You can see this in the righthand facets where the extreme values of the confidence interval ribbons are no longer drawn, as the fall outside of the imposed axis limits.
In the future I may be able to find a method which somehow gets around this, but for now it is what it is.
Function code:
#' Scale individual facet y-axes
#'
#'
#' VERY hacky method of imposing facet specific y-axis limits on plots made with facet_wrap
#' Briefly, this function alters an internal function within the ggproto object, a function which is called to find any limits imposed on the axes of the plot.
#' We wrap that function in a function of our own, one which intercepts the return value and modifies it with the axis limits we've specified the parent call
#'
#' I MAKE NO CLAIMS TO THE STABILITY OF THIS FUNCTION
#'
#'
#' @param plot The ggproto object to be modified
#' @param ylims A list of tuples specifying the y-axis limits of the individual facets of the plot. A NULL value in place of a tuple will indicate that the plot should draw that facet as normal (i.e. no axis modification)
#'
#' @return The original plot, with facet y-axes modified as specified
#' @export
#'
#' @examples
#' Not intended to be added to a ggproto call list.
#' This is a standalone function which accepts a ggproto object and modifies it directly, e.g.
#'
#' YES. GOOD:
#' ======================================
#' plot = ggplot(data, aes(...)) +
#' geom_whatever() +
#' geom_thing()
#'
#' scale_individual_facet_y_axes(plot, ylims)
#' ======================================
#'
#' NO. BAD:
#' ======================================
#' ggplot(data, aes(...)) +
#' geom_whatever() +
#' geom_thing() +
#' scale_individual_facet_y_axes(ylims)
#' ======================================
#'
scale_inidividual_facet_y_axes = function(plot, ylims) {
init_scales_orig = plot$facet$init_scales
init_scales_new = function(...) {
r = init_scales_orig(...)
# Extract the Y Scale Limits
y = r$y
# If this is not the y axis, then return the original values
if(is.null(y)) return(r)
# If these are the y axis limits, then we iterate over them, replacing them as specified by our ylims parameter
for (i in seq(1, length(y))) {
ylim = ylims[[i]]
if(!is.null(ylim)) {
y[[i]]$limits = ylim
}
}
# Now we reattach the modified Y axis limit list to the original return object
r$y = y
return(r)
}
plot$facet$init_scales = init_scales_new
return(plot)
}
scale_y_continuous
orcoord_cartesian
) are applicable facet-by-facet. If these are extensions of the data scale, I've also done this by adding fake data to the data set (and doing whatever's necessary to make sure it is considered in defining scales, but not plotted). It may also be possible to use thebreaks()
function to hack this, by detecting which subplot is currently being considered ... – Axempg
which is a built-in dataset toggplot2
– Jujitsuscale_y_continuous(breaks=my_breaks,expand=expand_scale(mult= c(0,.1)))
, through which themy_break
function set the breaks andexpand_scale
set the limits. – Noggin