Escala personalizada del eje y y etiquetas secundarias del eje y en ggplot2 3.1.0

Edita

arece que el comportamiento defectuoso desec_axis en ggplot2 3.1.0 es un error. Esto ha sido reconocido por los desarrolladores y están trabajando en una solución (verhil en GitHub).

Go

Tengo un gráfico en el que el eje y varía de 0 a 1. Me gustaría agregar un eje y secundario que varía de 0 a 0.5 (es decir, exactamente la mitad de los valores del eje y primario). Hasta ahora no hay problema.

Lo que complica el asunto es que tengo una transformación personalizada, para el eje y donde parte del eje y se muestra linealmente y el resto logarítmicamente (vea el código a continuación para ver un ejemplo). Para referencia, veaesta publicació oést.

Problem

Esto funcionó a la perfección con ggplot2 versión 3.0.0, pero ya no funciona con la versión más reciente (3.1.0). Ver ejemplo a continuación. No sé cómo solucionarlo en la versión más reciente.

Desde el changelog:

sec_axis () y dup_axis () ahora devuelven saltos apropiados para el eje secundario cuando se aplican a escalas transformadas de registro

Esta nueva funcionalidad parece romperse en el caso de los ejes y de transformación mixta.

Ejemplo reproducible

Aquí hay un ejemplo con la versión más reciente (3.1.0) de ggplot2:

library(ggplot2)
library(scales)

#-------------------------------------------------------------------------------------------------------
# Custom y-axis
#-------------------------------------------------------------------------------------------------------

magnify_trans_log <- function(interval_low = 0.05, interval_high = 1,  reducer = 0.05, reducer2 = 8) {

  trans <- Vectorize(function(x, i_low = interval_low, i_high = interval_high, r = reducer, r2 = reducer2) {
    if(is.na(x) || (x >= i_low & x <= i_high)) {
      x
    } else if(x < i_low & !is.na(x)) {
      (log10(x / r)/r2 + i_low)
    } else {
      log10((x - i_high) / r + i_high)/r2
    }
  })

  inv <- Vectorize(function(x, i_low = interval_low, i_high = interval_high, r = reducer, r2 = reducer2) {
    if(is.na(x) || (x >= i_low & x <= i_high)) {
      x
    } else if(x < i_low & !is.na(x)) {
      10^(-(i_low - x)*r2)*r
    } else {
      i_high + 10^(x*r2)*r - i_high*r
    }
  })

  trans_new(name = 'customlog', transform = trans, inverse = inv, domain = c(1e-16, Inf))
}

#-------------------------------------------------------------------------------------------------------
# Create data
#-------------------------------------------------------------------------------------------------------

x <- seq(-1, 1, length.out = 1000)
y <- c(x[x<0] + 1, -x[x>0] + 1)

dat <- data.frame(
  x = x
  , y = y
)

#-------------------------------------------------------------------------------------------------------
# Plot using ggplot2
#-------------------------------------------------------------------------------------------------------

theme_set(theme_bw())
ggplot(dat, aes(x = x, y = y)) +
  geom_line(size = 1) +
  scale_y_continuous(
    , trans = magnify_trans_log(interval_low = 0.5, interval_high = 1, reducer = 0.5, reducer2 = 8)
    , breaks = c(0.001, 0.01, 0.1, 0.5, 0.6, 0.7, 0.8, 0.9, 1)
    , sec.axis = sec_axis(
      trans = ~.*(1/2)
      , breaks = c(0.001, 0.01, 0.1, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5)
    )
  ) + theme(
    axis.text.y=element_text(colour = "black", size=15)
  )

Esto produce la siguiente trama:

El etiquetado del eje y secundario es correcto para la parte logarítmica del eje (por debajo de 0.5) pero incorrecto para la parte lineal del eje.

Si instalo ggplot2 3.0.0 usando

require(devtools)
install_version("ggplot2", version = "3.0.0", repos = "http://cran.us.r-project.org")

y ejecuto el mismo código que el anterior, obtengo el siguiente gráfico, que es lo que quiero:

Preguntas

¿Hay alguna forma de solucionar este problema en la versión más reciente de ggplot2 (3.1.0)? Idealmente, me gustaría abstenerme de usar una versión anterior de ggplot2 (es decir, 3.0.0). ¿Hay alternativas asec_axis que funcionaría en este caso?

Respuestas a la pregunta(2)

Su respuesta a la pregunta