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:
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.
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:
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))
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))
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))
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.
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:
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: