How to write a ggplot function '+' - pipeable, which can refer to the input graph

I am trying to write a function that can be called using ggplot2 syntax based on "+".

myplot + myfunction

In particular, the function I'm writing symmetrizes the y axis around zero, so it needs to determine the range of the y axis for the input graph.

So let

ylim_sym <- function(p){
    get_y_range <- function(p){
        ggplot2::ggplot_build(p)$layout$panel_ranges[[1]]$y.range
        }
    max_offset <- max(abs(get_y_range(p)))
    p + ylim(- max_offset, max_offset)
}

Using this function, the following actions are performed:

qplot(x = 1:10, y = exp(rnorm(10))) %>% ylim_sym()

But this does not work due to some priority issue between +.ggand %>%:

qplot(x = 1:10, y = exp(rnorm(10))) +
    geom_abline(slope = 0) %>%
    ylim_sym()

(I could write the latter (all_my_ggplot_pipeline) %>% ylim_sym(), but this is a pretty ugly syntax).

Ideally, I would like to write ylim_symso that it can be transmitted in this way through channels,

qplot(x = 1:10, y = exp(rnorm(10))) + ylim_sym()

but I can’t figure out how to access the schedule on the LHS +insideylim_sym

Any ideas?

+4
2

, .

StatSymYLim <- ggproto(
  "StatSymYLim", Stat, 
  compute_group = function(data, scales) {
    out <- data.frame(
      x = median(data$x),
      y = c(-1, 1) * max(abs(data$y))
      )
    out
    },
    required_aes = c("x", "y")
  )

ylim_sym <- function(...){
  geom_blank(..., stat = StatSymYLim)
  }

:

qplot(x = 1:10, y = exp(rnorm(10))) +
  geom_abline(slope = 0) +
  ylim_sym()

ggplot2 , , .

+5

:

ggfun, :

# devtools::install_github("moodymudskipper/ggfun")
library(ggfun)

ylim_sym <- function(p){
  get_y_range <- function(p){
    ggplot2::ggplot_build(p)$layout$panel_params[[1]]$y.range
  }
  max_offset <- max(abs(get_y_range(p)))
  p + ylim(- max_offset, max_offset)
}

qplot(x = 1:10, y = exp(rnorm(10))) +
  geom_abline(slope = 0) +
  ylim_sym
0

Source: https://habr.com/ru/post/1690722/


All Articles