2010-10-14 13 views
133

Como dice el título: ¿Cómo puedo trazar una leyenda fuera del área de trazado cuando uso gráficos base?¿Trazar una leyenda fuera del área de trazado en gráficos base?

pensé en perder el tiempo con layout y producir una trama vacía a sólo contienen la leyenda, pero yo estaría interesado en una forma usando sólo las instalaciones del gráfico de base y, por ejemplo, par(mar =) para conseguir un poco de espacio a la derecha de la trama para la leyenda.


Aquí un ejemplo:

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

Pero como se ha dicho, me gustaría que la leyenda para estar fuera del área de trazado (por ejemplo, a la derecha del gráfico/gráfico.

+0

... también se puede piratear la par con contenedor ciego para la leyenda, el tiempo de vida fácil y muy conveniente. Pregunta similar [aquí] (http://stackoverflow.com/questions/8736647/adding-legend-annotate-to-rs-plot-similar-to-rs-ggplot). – hhh

+2

@hhh El enlace ya no funciona. ¿Puedes actualizarlo o publicar una respuesta usando este enfoque? – Henrik

Respuesta

84

Tal vez lo que necesita es par(xpd=TRUE) para permitir cosas que deben extraerse fuera de la región trama. Entonces, si haces la trama principal con bty='L', tendrás un espacio a la derecha para ver una leyenda. Normalmente esto conseguiría recortado a la región trama, pero hacer par(xpd=TRUE) y con un poco de ajuste se puede obtener una leyenda tan a la derecha como puede ir:

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)) 
+29

Tenga en cuenta que puede pasar xpd directamente a la leyenda, por lo que no tendrá que preocuparse por restablecer el par después. También vea grconvertX & Y para una forma de especificar la ubicación de la leyenda de una manera que no dependa de los límites de los datos que está trazando. – Charles

+5

ya que esta pregunta y respuesta siguen siendo muy populares, 'par (xpd = NA)' es aún más potente (es decir, traza a más regiones). – Henrik

+0

+1. Deberíamos mencionar que tiene sentido tener una llamada 'par' separada justo antes de la leyenda. En mi trama, utilicé 'par (nuevo = T)' en varias otras ocasiones y simplemente quería agregar el parámetro 'xpd' en la misma llamada, lo que causa problemas. –

2

Pruebe layout() que tengo u sed por esto en el pasado simplemente creando un gráfico vacío debajo, correctamente escalado alrededor de 1/4 aproximadamente y colocando manualmente las partes de la leyenda.

Hay algunas preguntas más antiguas acerca de legend() que deberían comenzar.

+0

Como ya dije en la pregunta, esto es en lo que también pensé. Pero sería ideal, si hubiera otra manera. De alguna manera, supongo que no. – Henrik

6

Solo puedo ofrecer un ejemplo de la solución de diseño ya indicada.

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

an ugly picture :S

12

Lo siento por resucitar un viejo hilo, pero yo estaba con el mismo problema hoy La forma más sencilla que he encontrado es la siguiente:

# 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) 

encontrado aquí: http://www.harding.edu/fmccown/R/

+3

Aún mejor es oldpar <- par (XPD = T, Mar = par() $ mar + c (0,0,0,6)) ... par (oldpar) (Ver la ayuda de par) – rakensi

111

Nadie ha mencionado el uso de inset valores negativos para legend. Aquí hay un ejemplo, donde la leyenda está a la derecha de la gráfica, alineada a la parte superior (usando la palabra clave "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") 

El primer valor de inset=c(-0.2,0) podría ser necesario ajustar en base a la anchura de la leyenda.

legend_right

+0

realmente agradable. y parece funcionar sin 'xpd = TRUE'. – Henrik

+9

@Henrik no, no funciona sin xpd = TRUE. También tenga en cuenta que es mejor establecer xpd = TRUE como argumento de la función legend(). –

+0

A veces 'xpd' debe establecerse en' TRUE' para que el recuadro negativo funcione. Pero a veces no. Con el comando 'args.legend = list (x =" bottom ", horiz = TRUE, inserción = -0.2) 'dentro de un' barplot (... 'no parece necesitar' xpd = TRUE' pero con '' legend (x = "bottom", horiz = TRUE, inserción = -0.2) 'parece Necesito 'xpd = TRUE'. ¿Alguna idea? ¿Estoy confundido al pasar mis argumentos? – user3386170

2

Usted puede hacer esto con la Plotly R API, ya sea con el código, o desde la interfaz gráfica de usuario arrastrando la leyenda donde lo desee.

Aquí hay un ejemplo. El gráfico y el código también son here.

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) 

Puede colocar la leyenda fuera del gráfico asignando uno de los valores x e y a 100 o -100.

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

Estas son las otras opciones:

  • list("x" = 100, "y" = 0) para Fuera Abajo a la derecha
  • list("x" = 100, "y"= 1) Fuera Derecho Superior
  • list("x" = 100, "y" = .5) fuera justo al Medio
  • list("x" = 0, "y" = -100) Bajo Izquierda
  • list("x" = 0.5, "y" = -100) Bajo Ce nter
  • list("x" = 1, "y" = -100) Bajo Derecha

Entonces la respuesta.

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

argumentalmente devuelve una URL con su gráfico cuando se hace una llamada. Puede acceder a eso más rápidamente llamando al browseURL(response$url) para que abra su gráfico en su navegador.

url = response$url 
filename = response$filename 

Esto nos da este gráfico. También puede mover la leyenda desde la GUI y luego el gráfico se escalará en consecuencia. Divulgación completa: estoy en el equipo de Plotly.

Legend on side of graph

21

Otra solución, además de los ya mencionados ondes (usando layout o par(xpd=TRUE)) es para superponer su trama con una trama transparente sobre todo el dispositivo y luego añadir la leyenda a eso.

El truco consiste en superponer un gráfico (vacío) en toda el área de trazado y agregar la leyenda a eso. Podemos usar la opción par(fig=...). En primer lugar instruimos R para crear una nueva parcela en el transcurso de todo el dispositivo de trazado:

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

ajuste es necesario oma y mar ya que quieren tener el interior de la parcela cubre todo el dispositivo. new=TRUE es necesario para evitar que R inicie un nuevo dispositivo. a continuación, podemos añadir la trama vacío:

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

Y estamos listos para agregar la leyenda:

legend("bottomright", ...) 

añadirá una leyenda en la parte inferior derecha del dispositivo. Del mismo modo, podemos agregar la leyenda al margen superior o derecho. Lo único que tenemos que asegurar es que el margen de la trama original sea lo suficientemente grande como para acomodar la leyenda.

Poniendo todo esto en una función;

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(...) 
} 

Y un ejemplo.En primer lugar crear la trama asegurarnos de tener suficiente espacio en la parte inferior para agregar la leyenda:

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

A continuación, agregue la leyenda

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

El resultado es:

Example figure shown legend in top margin

+2

Gran adición a la lista aquí. Hay una explicación acerca de cómo hacer que esto funcione con múltiples gráficos en el gráfico [aquí] (http: // dr-k-lo.blogspot.com/2014/03/the-simplest-way-to-plot-legend-outside.html). – shiri

+0

El mejor truco! Funciona limpio! – Facottons

+0

Ene, hay una manera de aumentar la fuente tamaño en la leyenda, sin texto recortado? Por ejemplo, tengo un gráfico de 4 tipos diferentes de etiquetas, pero con un montón de espacio vacío entre ellos. –

7

Recientemente encontró una función muy fácil e interesante para imprimir leyendas fuera del área de la trama donde lo desea.

Haga el margen exterior en el lado derecho de la gráfica.

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

crear un gráfico

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") 

leyenda Agregar y sólo tiene que utilizar el localizador (1) función que, como a continuación. Luego debe hacer clic donde desee después de cargar el siguiente script.

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

Inténtelo

11

me gusta hacerlo de esta manera:

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

enter image description here

La única ajustes requeridos es en la fijación del margen derecho de ser lo suficientemente amplia como para dar cabida a la leyenda.

Sin embargo, esto también puede ser automatizado:

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

enter image description here

+0

Usando xpd = T o xpd = NA doesn ' t evitar mi 'principal' (t itle) de ser recortado cuando se estira para tratar de usar el área añadida con el amplio margen derecho. –

+0

@PhilGoetz ¿está seguro de que está trazando la línea principal dentro del área de trazado? ¿Es posible que no tengas suficientes líneas de margen para trazar? – jbaums

Cuestiones relacionadas