2012-04-28 8 views
10

Vorrei sapere come creare un grafico in R in cui l'asse y è invertito in modo tale che i dati tracciati appaiano in quello che sarebbe il quarto quadrante (IV) di un aereo cartesiano, al contrario del primo (I) quadrante.Come invertire l'asse y su un grafico

Per riferimento, la trama che sto cercando di fare è molto simile alla seguente (source):

a plot with inverted y-axis

ho trovato una serie di domande in linea di pertinenza invertire la numerazione sulla asse y, ma questi tutti ancora tracciano i dati nel primo quadrante. Qualcuno può suggerire come potrei produrre una trama simile a quella mostrata sopra?

+1

nella chiamata trama , specifica 'axes = FALSE', e poi usa' axis() 'un paio di volte, specificando l'argomento' side' per ottenere i tuoi assi dove vuoi t orlare. –

+3

Vado al commento del secondo tim: non sembra che tu stia davvero "invertendo" qualsiasi cosa. Stai semplicemente disegnando l'asse x in alto anziché in basso. – joran

risposta

10

solo per fornire una risposta elaborato, in seguito alle osservazioni di @timriffe e @joran ...

utilizzare la funzione di registro minore zecche da 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) 

} 

fare alcuni dati di esempio riproducibili :

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

trama senza assi:

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 

Aggiungere asse di registro di fantasia e svoltare a destra etichette delle tacche fino (grazie @joran!):

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

Aggiungere asse x la parte superiore:

axis(3) 

Aggiungi etichetta asse x (grazie per il suggerimento, @WojciechSobala)

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

E aggiungere un'annotazione alla fine della linea

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

Ecco il risultato:

enter image description here

+1

+1 Ben fatto. Non è necessario caricare un'altra immagine per dimostrarlo, ma poiché l'OP chiederà sicuramente, passare 'las = 1' a' minor.ticks.axis' fa ruotare le etichette dell'asse y in orizzontale? – joran

+0

@joran, buona idea, fatto! – Ben

+1

Con mtext è possibile aggiungere un'etichetta dell'asse x per ottenere il risultato desiderato. –

1

Rispondendo alla domanda nel titolo, l'/ modo più semplice per invertire l'asse è quello di capovolgere le limit variabili intorno:

> 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

Facendo in questo modo significa che non c'è bisogno di pasticciare con gli assi che sono diverse dalle coordinate dell'immagine.

Questo può essere combinato con il 'xaxt = 'n'' parametro e un comando aggiuntivo axis per posizionare un asse su un altro lato:

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

Inverted graph with X axis on top

0

Ora è abbastanza facile da invertire la asse y utilizzando scale_y_reverse e specificare position = "top" per l'asse x in ggplot2

Esempio

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

Se vogliamo sia logaritmica e l'asse inverso, abbiamo bisogno di una soluzione suggerita here come ggplot2 non hanno questa opzione 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

Problemi correlati