Trazar una leyenda fuera del área de trazado en gráficos base?


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

Pensé en juguetear con layout y producir una parcela vacía para contener solo la leyenda, pero me interesaría una forma de usar solo las instalaciones del gráfico base y, por ejemplo, par(mar = ) para obtener algo de espacio a la derecha de la parcela 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:

texto alt

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

 144
Author: Henrik, 2010-10-14

10 answers

Tal vez lo que necesita es par(xpd=TRUE) para permitir que las cosas se dibujen fuera de la región de la trama. Así que si haces la trama principal con bty='L' tendrás algo de espacio a la derecha para una leyenda. Normalmente esto se recortaría a la región de la trama, pero haga par(xpd=TRUE) y con un poco de ajuste puede obtener una leyenda tan a la derecha como pueda 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))
 92
Author: Spacedman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-12 15:04:18

Nadie ha mencionado el uso de valores negativos inset para legend. Aquí hay un ejemplo, donde la leyenda está a la derecha de la parcela, 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 necesitar un ajuste basado en el ancho de la leyenda.

legend_right

 122
Author: Mike T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-10 05:36:05

Otra solución, además de las ondes ya mencionadas (usando layout o par(xpd=TRUE)) es superponer su gráfico con un gráfico transparente sobre todo el dispositivo y luego agregar la leyenda a eso.

El truco es superponer un gráfico (vacío) sobre el área de trazado completa y agregar la leyenda a eso. Podemos usar la opción par(fig=...). Primero le indicamos a R que cree una nueva gráfica sobre 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 oma y mar es necesario ya que queremos tener el interior de la trama cubrir todo el dispositivo. new=TRUE es necesario para evitar que R inicie un nuevo dispositivo. Luego podemos agregar el gráfico 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. Asimismo, podemos añadir la leyenda al margen superior o derecho. Lo único que tenemos que asegurarnos es que el margen de la parcela 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. Primero cree la trama asegurándose de que tenemos 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)

Luego agregue la leyenda

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

Resultando en:

Figura de ejemplo que se muestra leyenda en el margen superior

 21
Author: Jan van der Laan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-14 16:06:31

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)

Se encuentra aquí: http://www.harding.edu/fmccown/R /

 12
Author: veiga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-24 18:02:43

Me gusta hacerlo así:

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

introduzca la descripción de la imagen aquí

El único ajuste requerido es establecer el margen derecho para que sea lo suficientemente ancho como para acomodar la leyenda.

Sin embargo, esto también se puede automatizar:

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

introduzca la descripción de la imagen aquí

 11
Author: jbaums,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-06 02:49:22

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

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 imagen fea: S

 7
Author: Roman Luštrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-14 11:01:00

Recientemente encontré una función muy fácil e interesante para imprimir leyenda fuera del área de la parcela donde desea.

Hacer el margen exterior en el lado derecho de la parcela.

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

Agregue la leyenda y simplemente use la función locator(1) como se muestra a continuación. Entonces usted tiene que hacer clic en 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))

Pruébalo

 7
Author: Vandka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-11 02:40:24

Puede hacer esto con la API Plotly R, ya sea con código, o desde la GUI arrastrando la leyenda donde lo desee.

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

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)

Aquí están las otras opciones:

  • list("x" = 100, "y" = 0) para el Exterior Inferior Derecho
  • list("x" = 100, "y"= 1) Fuera de la Parte superior Derecha
  • list("x" = 100, "y" = .5) Fuera del Centro Derecho
  • list("x" = 0, "y" = -100) Debajo de la izquierda
  • list("x" = 0.5, "y" = -100) En el centro
  • list("x" = 1, "y" = -100) A la derecha

Luego la respuesta.

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

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

url = response$url
filename = response$filename

Eso nos da este gráfico. También puede mover la leyenda desde la interfaz gráfica de usuario y luego el gráfico se escalará consecuentemente. Estoy en el equipo de Complotly.

Leyenda en el lado del gráfico

 3
Author: Mateo Sanchez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-20 21:20:14

Intente layout() que he usado para esto en el pasado simplemente creando un gráfico vacío a continuación, correctamente escalado alrededor de 1/4 o así y colocando las partes de la leyenda manualmente en él.

Aquí hay algunas preguntas más antiguas sobre legend() que deberían ayudarte a empezar.

 1
Author: Dirk Eddelbuettel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-14 10:17:27

Agregando otra alternativa simple que es bastante elegante en mi opinión.

Su parcela:

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:

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

Resultado:

imagen con leyenda

Aquí solo se agregó la segunda línea de la leyenda a su ejemplo. A su vez:

  • inset=c(0,1) - mueve la leyenda por fracción de la región de la gráfica en las direcciones (x,y). En este caso la leyenda está en la posición "bottomright". Se mueve por 0 regiones de trazado en la dirección x (por lo que permanece en "derecha") y por 1 trazado región en dirección y (de abajo hacia arriba). Y sucede que aparece justo encima de la trama.
  • xpd=TRUE - vamos a la leyenda aparece fuera de la región de trazado.
  • horiz=TRUE - instruye para producir una leyenda horizontal.
  • bty="n" - un detalle de estilo para deshacerse del cuadro delimitador de leyenda.

Lo mismo se aplica al agregar leyenda al lado:

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

Aquí simplemente ajustamos las posiciones de la leyenda y agregamos espacio de margen adicional al lado derecho de la gráfica. Resultado:

imagen con leyenda 2

 0
Author: Karolis Koncevičius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 22:00:05