I'm trying to make a facetted plot with two panels - left and right. The variable on the x-axis is continuous, and the variable on the y-axis is discrete, with relatively long labels. I would like to put the y-axis of the right hand side plot on the right side (and keep the y-axis of the left hand side left), so that the two panels are not split apart by the y-axis labels of the right hand side plot.
I've tried a couple of different workaround (e.g. cowplot
) but I can't get anything that I would be satisfied with, because I also need a legend in my plot.
Here's a reprex:
library(tidyverse)
region <- sample(words, 20)
panel <- rep(c(0, 1), each = 10)
value <- rnorm(20, 0, 1)
df <- tibble(region, panel, value)
ggplot(df, aes(value, region)) +
geom_point() +
facet_wrap(~ panel, scales = 'free_y')
Thank you!
This solution lacks flexibility for cases with more than 2 plots but it does the job for your case. The idea is to generate the plots separately and combine the plots into a list. The ggplot
function call contains an if else
function for the scale_y_discrete
layer which puts the y-axis either on the left-hand or right-hand side depending on the value of panel
. We use gridExtra
to combine the plots.
library(tidyverse)
library(gridExtra)
region <- sample(words, 20)
panel <- rep(c(0, 1), each = 10)
value <- rnorm(20, 0, 1)
df <- tibble(region, panel, value)
panel <- sort(unique(df$panel))
plot_list <- lapply(panel, function(x) {
ggplot(data = df %>% filter(panel == x),
aes(value, region)) +
geom_point() +
if (x == 0) scale_y_discrete(position = "left") else scale_y_discrete(position = "right")
})
do.call("grid.arrange", c(plot_list, ncol = 2))
You can leave the facet_wrap(~ panel, scales = 'free_y')
layer and you will retain the strips at the top in the plot.
UPDATE
Code updated to remove x-axis from the individual plots and add text at the bottom location of the grid plot; added a second if else
to suppress the y-axis title in the right hand plot. Note that the if else
functions need to be enclosed by curly brackets (did not know that either :-) but it makes sense):
plot_list <- lapply(panel, function(x) {
ggplot(data = df %>% filter(panel == x), aes(x = value, y = region)) +
geom_point() +
theme(axis.title.x = element_blank()) +
facet_wrap(. ~ panel) +
{if (x == 0) scale_y_discrete(position = "left") else scale_y_discrete(position = "right")} +
{if (x == 1) theme(axis.title.y = element_blank())}
})
do.call("grid.arrange", c(plot_list, ncol = 2, bottom = "value"))