teunbrand / ggh4x

ggplot extension: options for tailored facets, multiple colourscales and miscellaneous
https://teunbrand.github.io/ggh4x/
Other
563 stars 33 forks source link

cannot condition y-scales on the column values of facet_grid2 inside facetted_pos_scales #61

Closed yjunechoe closed 2 years ago

yjunechoe commented 2 years ago

The problem arose when trying to achieve the following layout, where the y-axis labels and breaks are NULL when sex == "male"

My first attempt was the following with facetted_pos_scales(), but it seems to get ignored and produces the same plot without that line:

base <- na.omit(palmerpenguins::penguins) %>% 
  ggplot() +
  geom_point(aes(x = bill_length_mm, y = body_mass_g, color = species)) +
  theme_classic()

base +
  ggh4x::facet_grid2(species ~ sex, axes = "all", scales = "free_y") +
  ggh4x::facetted_pos_scales(y = list(
    sex == "female" ~ scale_y_continuous(),
    sex == "male" ~ scale_y_continuous(guide = guide_axis_manual(labels = NULL, breaks = NULL))
  ))

### Looks the same as this:
# base +
#    ggh4x::facet_grid2(species ~ sex, axes = "all", scales = "free_y")

Interestingly the conditions do get applied if I switch the order of species ~ sex to sex ~ species inside facet_grid2(), such that the sex variable is now in the rows instead of columns.

base +
  ggh4x::facet_grid2(sex ~ species, axes = "all", scales = "free_y") +
  ggh4x::facetted_pos_scales(y = list(
    sex == "female" ~ scale_y_continuous(),
    sex == "male" ~ scale_y_continuous(guide = guide_axis_manual(labels = NULL, breaks = NULL))
  ))

This same asymmetry is also found for switching x-scales with facetted_pos_scales() as well (it can be conditioned on column values but not row values).

I may be approaching the problem wrong, and any pointers would be appreciated - thanks in advance!

teunbrand commented 2 years ago

Hi there,

Thanks for letting me know!

I think the underlying issue in this case is the typical constraint of grid-style facets that scales cannot vary within rows and columns. You could use independent argument in facet_grid2() to relieve this constraint, but that gives the wrong interpretation of the plot if you hide breaks and labels, as one would assume that the breaks on the left y-axis also apply to the right panel (which they do not, which you can see if you remove the guide in the plot below).

library(ggh4x)
library(dplyr)

base <- na.omit(palmerpenguins::penguins) %>% 
  ggplot() +
  geom_point(aes(x = bill_length_mm, y = body_mass_g, color = species)) +
  theme_classic()

base +
  ggh4x::facet_grid2(species ~ sex, axes = "all", scales = "free_y", independent = "y") +
  ggh4x::facetted_pos_scales(y = list(
    sex == "female" ~ scale_y_continuous(),
    sex == "male" ~ scale_y_continuous(guide = guide_axis_manual(labels = NULL, breaks = NULL))
  ))

Created on 2022-02-03 by the reprex package (v2.0.1)

The simplest solution in this case would be to keep the x-axes, discard the inner y-axes and draw a line instead of formally having an axis.

base + 
  facet_grid2(species ~ sex, axes = "x", scales = "free_y") +
  geom_segment(
    data = data.frame(sex = "male"),
    aes(x = -Inf, xend = -Inf, y = -Inf, yend = Inf),
    size = 1
  )

yjunechoe commented 2 years ago

Thanks so much for the quick reply! This suits my purpose - the geom_segment trick is also super neat!