2012-04-28 13 views
10

Me gustaría saber cómo hacer un trazado en R donde el eje y está invertido de modo que los datos trazados aparezcan en lo que sería el cuarto cuadrante (IV) de un plano cartesiano, a diferencia del primer (I) cuadrante.Cómo invertir el eje y en un gráfico

Como referencia, la trama que estoy tratando de hacer que se ve muy similar a la siguiente (source):

a plot with inverted y-axis

Me han encontrado una serie de preguntas en línea perteneciente a la inversión de la numeración en el eje y, pero todos estos aún trazan los datos en el primer cuadrante. ¿Alguien puede sugerir cómo podría producir una trama similar a la que se muestra arriba?

+1

en su llamada trama , especifique 'axes = FALSE', y luego use' axis() 'un par de veces, especificando el argumento' side' para obtener sus ejes donde desee t dobladillo. –

+3

Voy a hacer un comentario del segundo timón: no parece que realmente estés "invirtiendo" nada. Estás trazando el eje x en la parte superior en lugar de en la parte inferior. – joran

Respuesta

10

sólo para proporcionar una respuesta elaborado, siguiendo los comentarios de @timriffe y @joran ...

utilizar la función de registro de marcas secundarias de this answer:

minor.ticks.axis <- function(ax,n,t.ratio=0.5,mn,mx,...){ 

    lims <- par("usr") 
    if(ax %in%c(1,3)) lims <- lims[1:2] else lims[3:4] 

    major.ticks <- pretty(lims,n=5) 
    if(missing(mn)) mn <- min(major.ticks) 
    if(missing(mx)) mx <- max(major.ticks) 

    major.ticks <- major.ticks[major.ticks >= mn & major.ticks <= mx] 

    labels <- sapply(major.ticks,function(i) 
    as.expression(bquote(10^ .(i))) 
        ) 
    axis(ax,at=major.ticks,labels=labels,...) 

    n <- n+2 
    minors <- log10(pretty(10^major.ticks[1:2],n))-major.ticks[1] 
    minors <- minors[-c(1,n)] 

    minor.ticks = c(outer(minors,major.ticks,`+`)) 
    minor.ticks <- minor.ticks[minor.ticks > mn & minor.ticks < mx] 


    axis(ax,at=minor.ticks,tcl=par("tcl")*t.ratio,labels=FALSE) 

} 

hacer un poco de datos de ejemplo reproducibles :

x <- 1:8 
y <- 10^(sort(runif(8, 1, 10), decreasing = TRUE)) 

Parcela sin ejes:

plot(x, log10(y), # function to plot 
xlab="",   # suppress x labels 
type = 'l',  # specify line graph 
xlim = c(min(x), (max(x)*1.3)), # extend axis limits to give space for text annotation 
ylim = c(0, max(log10(y))),  # ditto 
axes = FALSE) # suppress both axes 

Añadir eje de registro de lujo y gire etiquetas señalizadoras derecha hacia arriba (gracias @joran!):

minor.ticks.axis(2, 9, mn=0, mx=10, las=1) 

Añadir eje x hasta la parte superior:

axis(3) 

Añadir etiqueta del eje x (gracias por la punta, @WojciechSobala)

mtext("x", side = 3, line = 2) 

Y añadir una anotación al final de la línea

text(max(x), min(log10(y)), "Example", pos = 1) 

Aquí está el resultado:

enter image description here

+1

+1 Bien hecho. No tiene que cargar otra imagen para probarlo, pero dado que seguramente el OP preguntará, ¿pasar las 'y = 1' a' minor.ticks.axis' hace rotar las etiquetas del eje y para que sean horizontales? – joran

+0

@joran, buena idea, hecho! – Ben

+1

Con mtext puede agregar la etiqueta del eje X para obtener el resultado deseado. –

1

Respondiendo a la pregunta del título, el mejor/manera más fácil para invertir el eje es voltear los limit las variables de todo:

> plot(1:10, xlim=c(1,10)); 

standard plot

> plot(1:10, xlim=c(10,1)); 

plot with inverted X axis

> plot(1:10, ylim=c(10,1)); 

plot with inverted Y axis

Hacerlo de esta manera significa que no es necesario perder el tiempo con ejes que son diferentes de las coordenadas de la imagen.

Esto se puede combinar con el 'xaxt = 'n'' parámetro y un comando adicional axis para colocar un eje en otro lado:

> plot(1:10, ylim=c(10,1), xaxt="n"); axis(3); 

Inverted graph with X axis on top

0

Es ahora bastante fácil de invertir la eje y usando scale_y_reverse y especificar position = "top" para el eje x en ggplot2

Ejemplo

library(ggplot2) 
library(scales) 

set.seed(99) 
Date <- seq(from = as.Date("2017-12-01"), to = as.Date("2017-12-15"), 
      by = "days") 
Flux <- runif(length(Date), 1, 10000) 
Flux_df <- data.frame(Date, Flux) 

p1 <- ggplot(Flux_df, aes(Date, Flux)) + 
    geom_col() + 
    xlab("") + 
    scale_x_date(position = "top", breaks = pretty_breaks(), expand = c(0, 0)) + 
    scale_y_reverse(expand = expand_scale(mult = c(0.2, 0))) + 
    theme_bw(base_size = 16) + 
    theme(panel.border = element_blank(), 
     panel.grid.major.x = element_blank(), 
     panel.grid.minor = element_blank(), 
     axis.line = element_line()) + 
    theme(legend.position = "none") 
p1 

enter image description here

Si queremos tanto logarítmica y el eje inversa, necesitamos una solución sugerida here como ggplot2 no tiene esa opción atm

reverselog_trans <- function(base = exp(1)) { 
    trans <- function(x) -log(x, base) 
    inv <- function(x) base^(-x) 
    scales::trans_new(paste0("reverselog-", format(base)), trans, inv, 
        scales::log_breaks(base = base), domain = c(1e-100, Inf)) 
} 


p1 + scale_y_continuous(trans = reverselog_trans(10), 
         breaks = scales::trans_breaks("log10", function(x) 10^x), 
         labels = scales::trans_format("log10", scales::math_format(10^.x)), 
         expand = expand_scale(mult = c(0.2, 0))) + 
    annotation_logticks() 

enter image description here

Cuestiones relacionadas