rggplot2ggh4x

List generation of ggplot2 scale_y_continuous()


I am trying to generate a named list of ggplot2 y-scales for usage with facet plot in combination with `

facetted_pos_scales(x = NULL, y = NULL)` from the ggh4x package.

The ultimate goal is to scale the facets' secondary y-axes independently of each other. The limits for secondary y-scales are saved in a data frame. I fail to (1) create a named list for each row [more precisely, I cannot evaluate the column Name to its respective value, e.g. "A"] and (2) force the evaluation of the arguments to the transformation function at the time of the list creation [e.g. min_to -> 0 etc.].

library(ggplot2)
library(scales)

df = tibble(Name = c('A','B'), 
       min_from = c(0,0), 
       max_from = c(1,1), 
       min_to = c(100,100), 
       max_to = c(1000,1000))
df |> 
  group_by(Name) |> 
  mutate(y_scale = list(Name = scale_y_continuous(
    sec.axis = sec_axis(transform = \(x) rescale(x, 
                                              to = c(min_to, max_to), 
                                              from = c(min_from, max_from)))
    )))

Solution

  • Not sure whether is necessary to have the scales stored inside a list column. Personally I would simply use a list, e.g. you could use split and lapply to create a list of scales which you could then pass to ggh4x::facetted_pos_scales:

    library(ggplot2)
    library(scales)
    library(ggh4x)
    
    scale_y <- df |>
      split(~Name) |>
      lapply(\(sc) {
        scale_y_continuous(
          sec.axis = sec_axis(transform = \(x) rescale(x,
            to = c(sc$min_to, sc$max_to),
            from = c(sc$min_from, sc$max_from)
          ))
        )
      })
    
    scale_y
    #> $A
    #> <ScaleContinuousPosition>
    #>  Range:  
    #>  Limits:    0 --    1
    #> 
    #> $B
    #> <ScaleContinuousPosition>
    #>  Range:  
    #>  Limits:    0 --    1
    
    data.frame(
      x = 1:10, y = 1:10, Name = rep(c("A", "B"), each = 10)
    ) |>
      ggplot(aes(x, y)) +
      geom_point() +
      facet_wrap(~Name, scales = "free_y") +
      ggh4x::facetted_pos_scales(y = scale_y)