Tracciare una legenda al di fuori dell’area di disegno nella grafica di base?

Come dice il titolo: Come posso tracciare una legenda al di fuori dell’area di disegno quando si utilizza la grafica di base?

Ho pensato di manipolare il layout e produrre un grafico vuoto per contenere solo la legenda, ma sarei interessato in un modo usando solo le funzioni del grafico di base e ad esempio, par(mar = ) per ottenere spazio sulla destra della trama per la leggenda.


Ecco un esempio:

 plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch = 2, lty = 2, type="o") legend(1,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2)) 

produce:

alt text

Ma come detto, vorrei che la legenda fosse al di fuori dell’area di disegno (ad esempio, a destra del grafico / della trama.

Forse ciò di cui hai bisogno è par(xpd=TRUE) per abilitare le cose da disegnare al di fuori dell’area della trama. Quindi se fai la trama principale con bty='L' avrai uno spazio a destra per una leggenda. Normalmente questo viene troncato nella regione della trama, ma viene par(xpd=TRUE) e con un po ‘di aggiustamento è ansible ottenere una legenda il più a destra ansible:

  set.seed(1) # just to get the same random numbers par(xpd=FALSE) # this is usually the default plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2), bty='L') # this legend gets clipped: legend(2.8,0,c("group A", "group B"), pch = c(1,2), lty = c(1,2)) # so turn off clipping: par(xpd=TRUE) legend(2.8,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2)) 

Nessuno ha menzionato l’utilizzo di valori di inset negativi per la legend . Ecco un esempio, in cui la legenda è a destra della trama, allineata in alto (usando la parola chiave "topright" ).

 # Random data to plot: A < - data.frame(x=rnorm(100, 20, 2), y=rnorm(100, 20, 2)) B <- data.frame(x=rnorm(100, 21, 1), y=rnorm(100, 21, 1)) # Add extra space to right of plot area; change clipping to figure par(mar=c(5.1, 4.1, 4.1, 8.1), xpd=TRUE) # Plot both groups plot(y ~ x, A, ylim=range(c(A$y, B$y)), xlim=range(c(A$x, B$x)), pch=1, main="Scatter plot of two groups") points(y ~ x, B, pch=3) # Add legend to top right, outside plot region legend("topright", inset=c(-0.2,0), legend=c("A","B"), pch=c(1,3), title="Group") 

Il primo valore di inset=c(-0.2,0) potrebbe richiedere una modifica in base alla larghezza della legenda.

legend_right

Un’altra soluzione, oltre alle ondes già menzionate (usando layout o par(xpd=TRUE) ) è di sovrapporre la trama con una trama trasparente sull’intero dispositivo e quindi aggiungere la legenda a questo.

Il trucco è sovrapporre un grafico (vuoto) sull’area di disegno completa e aggiungere la legenda a questo. Possiamo usare l’opzione par(fig=...) . Per prima cosa chiediamo a R di creare una nuova trama sull’intero dispositivo di tracciamento:

 par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), mar=c(0, 0, 0, 0), new=TRUE) 

L’impostazione di oma e mar è necessaria poiché vogliamo che l’interno della trama copra l’intero dispositivo. new=TRUE è necessario per evitare che R avvii un nuovo dispositivo. Possiamo quindi aggiungere la trama vuota:

 plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n') 

E siamo pronti ad aggiungere la leggenda:

 legend("bottomright", ...) 

aggiungerà una legenda in basso a destra del dispositivo. Allo stesso modo, possiamo aggiungere la legenda al margine superiore o destro. L’unica cosa che dobbiamo assicurare è che il margine della trama originale sia abbastanza grande da contenere la leggenda.

Mettendo tutto questo in una funzione;

 add_legend < - function(...) { opar <- par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), mar=c(0, 0, 0, 0), new=TRUE) on.exit(par(opar)) plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n') legend(...) } 

E un esempio. Per prima cosa crea il grafico assicurandoti di avere abbastanza spazio in basso per aggiungere la legenda:

 par(mar = c(5, 4, 1.4, 0.2)) plot(rnorm(50), rnorm(50), col=c("steelblue", "indianred"), pch=20) 

Quindi aggiungi la legenda

 add_legend("topright", legend=c("Foo", "Bar"), pch=20, col=c("steelblue", "indianred"), horiz=TRUE, bty='n', cex=0.8) 

Con il risultato di:

Esempio di figura legenda mostrata nel margine superiore

Ci scusiamo per la risurrezione di un thread precedente, ma oggi mi trovavo con lo stesso problema. Il modo più semplice che ho trovato è il seguente:

 # Expand right side of clipping rect to make room for the legend par(xpd=T, mar=par()$mar+c(0,0,0,6)) # Plot graph normally plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch = 2, lty = 2, type="o") # Plot legend where you want legend(3.2,1,c("group A", "group B"), pch = c(1,2), lty = c(1,2)) # Restore default clipping rect par(mar=c(5, 4, 4, 2) + 0.1) 

Trovato qui: http://www.harding.edu/fmccown/R/

Mi piace farlo in questo modo:

 par(oma=c(0, 0, 0, 5)) plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch=2, lty=2, type="o") legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA, c("group A", "group B"), pch=c(1, 2), lty=c(1,2)) 

inserisci la descrizione dell'immagine qui

L’unico tweaking richiesto è impostare il margine giusto per essere sufficientemente ampio da contenere la legenda.

Tuttavia, questo può anche essere automatizzato:

 dev.off() # to reset the graphics pars to defaults par(mar=c(par('mar')[1:3], 0)) # optional, removes extraneous right inner margin space plot.new() l < - legend(0, 0, bty='n', c("group A", "group B"), plot=FALSE, pch=c(1, 2), lty=c(1, 2)) # calculate right margin width in ndc w <- grconvertX(l$rect$w, to='ndc') - grconvertX(0, to='ndc') par(omd=c(0, 1-w, 0, 1)) plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2, 2)) lines(1:3, rnorm(3), pch=2, lty=2, type="o") legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA, c("group A", "group B"), pch=c(1, 2), lty=c(1, 2)) 

inserisci la descrizione dell'immagine qui

Posso offrire solo un esempio della soluzione di layout già indicata.

 layout(matrix(c(1,2), nrow = 1), widths = c(0.7, 0.3)) par(mar = c(5, 4, 4, 2) + 0.1) plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch = 2, lty = 2, type="o") par(mar = c(5, 0, 4, 2) + 0.1) plot(1:3, rnorm(3), pch = 1, lty = 1, ylim=c(-2,2), type = "n", axes = FALSE, ann = FALSE) legend(1, 1, c("group A", "group B"), pch = c(1,2), lty = c(1,2)) 

una brutta foto: S

Recentemente ho trovato la funzione molto facile e interessante per stampare legenda al di fuori dell’area del tracciato dove vuoi.

Crea il margine esterno sul lato destro della trama.

 par(xpd=T, mar=par()$mar+c(0,0,0,5)) 

Crea una trama

 plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch = 2, lty = 2, type="o") 

Aggiungi una legenda e usa la funzione locator (1) come di seguito. Quindi devi solo cliccare dove vuoi dopo aver caricato lo script seguente.

 legend(locator(1),c("group A", "group B"), pch = c(1,2), lty = c(1,2)) 

Provalo

Puoi farlo con l’ API R Plotly , con entrambi i codici o dalla GUI trascinando la legenda dove vuoi.

Ecco un esempio. Anche il grafico e il codice sono qui .

 x = c(0,1,2,3,4,5,6,7,8) y = c(0,3,6,4,5,2,3,5,4) x2 = c(0,1,2,3,4,5,6,7,8) y2 = c(0,4,7,8,3,6,3,3,4) 

È ansible posizionare la legenda all’esterno del grafico assegnando uno dei valori x e y su 100 o -100.

 legendstyle = list("x"=100, "y"=1) layoutstyle = list(legend=legendstyle) 

Ecco le altre opzioni:

  • list("x" = 100, "y" = 0) per il lato inferiore destro
  • list("x" = 100, "y"= 1) Esterno Right Top
  • list("x" = 100, "y" = .5) Al di fuori del centro
  • list("x" = 0, "y" = -100) Sotto a sinistra
  • list("x" = 0.5, "y" = -100) Sotto al centro
  • list("x" = 1, "y" = -100) Sotto a destra

Quindi la risposta.

response = p$plotly(x,y,x2,y2, kwargs=list(layout=layoutstyle));

Plotly restituisce un URL con il tuo grafico quando fai una chiamata. Puoi accedervi più rapidamente chiamando browseURL(response$url) modo che apra il tuo grafico nel tuo browser.

 url = response$url filename = response$filename 

Questo ci dà questo grafico. È inoltre ansible spostare la legenda all’interno della GUI e quindi il grafico si ridimensionerà di conseguenza. Full disclosure: Sono nella squadra di Plotly.

Legenda sul lato del grafico

Prova layout() che ho usato per questo in passato semplicemente creando un grafico vuoto di seguito, correttamente ridimensionato a circa 1/4 o giù di lì e inserendo manualmente le parti della legenda in esso.

Qui ci sono alcune vecchie domande su legend() che dovrebbe iniziare.

Aggiungendo un’altra semplice alternativa che è abbastanza elegante secondo me.

La tua trama:

 plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch = 2, lty = 2, type="o") 

Leggenda:

 legend("bottomright", c("group A", "group B"), pch=c(1,2), lty=c(1,2), inset=c(0,1), xpd=TRUE, horiz=TRUE, bty="n" ) 

Risultato:

foto con la leggenda

Qui solo la seconda riga della legenda è stata aggiunta al tuo esempio. A sua volta:

  • inset=c(0,1) – sposta la legenda per frazione della regione di trama in direzioni (x, y). In questo caso la legenda è nella posizione "bottomright" . Viene spostato da 0 regioni di tracciamento in direzione x (quindi rimane a “destra”) e da 1 regione di tracciamento in direzione y (dal basso verso l’alto). E così accade che appare proprio sopra la trama.
  • xpd=TRUE – facciamo apparire la leggenda al di fuori dell’area di tracciamento.
  • horiz=TRUE – indica di produrre una legenda orizzontale.
  • bty="n" – un dettaglio di stile per eliminare il riquadro di delimitazione della legenda.

Lo stesso vale quando si aggiunge una legenda sul lato:

 par(mar=c(5,4,2,6)) plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2)) lines(1:3, rnorm(3), pch = 2, lty = 2, type="o") legend("topleft", c("group A", "group B"), pch=c(1,2), lty=c(1,2), inset=c(1,0), xpd=TRUE, bty="n" ) 

Qui abbiamo semplicemente regolato le posizioni delle legende e aggiunto spazio marginale aggiuntivo sul lato destro della trama. Risultato:

foto con la legenda 2