usar unidades npc en annotate ()

Sep 04 2020

Tengo un objeto ggplot. Me gustaría agregar algo de texto con annotate()y me gustaría especificar las coordenadas del texto en unidades npc. es posible?

Este ejemplo mínimo demuestra cómo el texto se coloca normalmente con annotate():

library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + annotate("text", x = 30, y = 4.5, label = "hello")

Me gustaría lograr el mismo efecto, pero en lugar de especificar xy yen coordenadas nativas, me gustaría especificarlas con coordenadas npc. Para el propósito de este ejemplo, no me preocupa traducir exactamente x = 30y y = 4.5en unidades npc. Solo quiero saber si las unidades npc se pueden usar annotate().

Hay dos estrategias relacionadas, pero no son del todo satisfactorias:

  1. Uno puede utilizar unidades de APN especificando que, por ejemplo, grid::textGrob(). Y luego uno puede colocar el grob con annotation_custom(), como en esta respuesta de @baptiste . Pero esta solución es un poco más engorrosa de lo que me gustaría.

  2. El paquete "ggpmisc" incluye geom_text_npc(). Pero aún no funciona con annotate(). Es decir, annotate("text_npc", ...)no parece funcionar. [Editar: ahora funciona. Vea el mensaje de Pedro Aphalo a continuación.]

También hay muchas publicaciones relacionadas. En particular, Greg Snow sugirió usar una cuadrícula para crear una ventana con las dimensiones py luego anotar esa ventana. Y @teunbrand ha sugerido un método que implica convertir pa un objeto "gtable" (con ggplotGrob()) y luego dibujar ese objeto "gtable". Cualquiera de estas estrategias probablemente pueda adaptarse a mis propósitos. Pero, ¿hay una forma más sencilla de usar las coordenadas npc con annotate()?

Respuestas

6 AllanCameron Sep 04 2020 at 20:31

Personalmente, usaría el método de Baptiste pero envuelto en una función personalizada para hacerlo menos torpe:

annotate_npc <- function(label, x, y, ...)
{
  ggplot2::annotation_custom(grid::textGrob(
    x = unit(x, "npc"), y = unit(y, "npc"), label = label, ...))
}

Lo que te permite hacer:

p + annotate_npc("hello", 0.5, 0.5)

Tenga en cuenta que esto siempre dibujará su anotación en el espacio npc de la ventana gráfica de cada panel en el gráfico (es decir, en relación con el área sombreada en gris en lugar de toda la ventana de trazado), lo que lo hace útil para las facetas. Si desea dibujar su anotación en coordenadas npc absolutas (para que tenga la opción de trazar fuera de la ventana gráfica del panel), sus dos opciones son:

  1. Desactive el recorte coord_cartesian(clip = "off")y aplique ingeniería inversa a las coordenadas x, y de las coordenadas npc dadas antes de usar annotate. Esto es complicado pero posible
  2. Dibuja directamente usando grid. Esto es mucho más fácil, pero tiene la desventaja de que la anotación debe dibujarse sobre la trama en lugar de ser parte de la trama en sí. Podrías hacer eso así:
annotate_npc_abs <- function(label, x, y, ...) 
{
  grid::grid.draw(grid::textGrob(
    label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}

Y la sintaxis sería un poco diferente:

p 
annotate_npc_abs("hello", 0.05, 0.75)

1 PedroAphalo Sep 11 2020 at 00:20

A partir de 'ggpmisc' (> = 0.3.6), el siguiente código funciona como se esperaba (en CRAN a partir del 10 de septiembre de 2020).

library(ggpmisc)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
# default justification is "inward"
p + annotate("text_npc", npcx = 0.8, npcy = 0.75, label = "hello")
# same justification as default for "geom_text()"
p + annotate("text_npc", npcx = 0.8, npcy = 0.75, label = "hello",
             hjust = "center", vjust = "middle")