use unidades npc em annotate ()
Eu tenho um objeto ggplot. Gostaria de adicionar algum texto com annotate()e gostaria de especificar as coordenadas do texto em unidades npc. Isso é possível?
Este exemplo mínimo demonstra como o texto é normalmente posicionado com annotate():
library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + annotate("text", x = 30, y = 4.5, label = "hello")
Gostaria de obter o mesmo efeito, mas em vez de especificar xe yem coordenadas nativas, gostaria de especificá-las com coordenadas npc. Para o propósito deste exemplo, não estou preocupado em traduzir exatamente x = 30e y = 4.5em unidades npc. Eu só quero saber se as unidades npc podem ser usadas em annotate()tudo.
Existem duas estratégias relacionadas, mas não são totalmente satisfatórias:
Pode-se usar unidades npc especificando-as como, digamos
grid::textGrob(),. E pode-se então colocar o grob comannotation_custom(), como nesta resposta de @baptiste . Mas essa solução é um pouco mais complicada do que eu gostaria.O pacote "ggpmisc" inclui
geom_text_npc(). Mas ainda não funciona comannotate(). Ou seja,annotate("text_npc", ...)não parece funcionar. [Editar: agora funciona. Veja a mensagem de Pedro Aphalo abaixo.]
Existem também muitas postagens relacionadas. Em particular, Greg Snow sugeriu o uso de grade para criar uma janela de visualização com as dimensões pe, a seguir, anotando essa janela de visualização. E @teunbrand sugeriu um método que envolve a conversão pem um objeto "gtable" (com ggplotGrob()) e, em seguida, o desenho desse objeto "gtable". Qualquer uma dessas estratégias provavelmente pode ser adaptada aos meus propósitos. Mas existe uma maneira mais direta de usar coordenadas npc com annotate()?
Respostas
Pessoalmente, eu usaria o método de Baptiste, mas envolvido em uma função personalizada para torná-lo menos desajeitado:
annotate_npc <- function(label, x, y, ...)
{
ggplot2::annotation_custom(grid::textGrob(
x = unit(x, "npc"), y = unit(y, "npc"), label = label, ...))
}
O que permite que você faça:
p + annotate_npc("hello", 0.5, 0.5)
Observe que isso sempre desenhará sua anotação no espaço npc da janela de visualização de cada painel no gráfico (ou seja, em relação à área sombreada em cinza ao invés de toda a janela de plotagem), o que o torna útil para facetas. Se você deseja desenhar sua anotação em coordenadas npc absolutas (para ter a opção de plotar fora da janela de visualização do painel), suas duas opções são:
- Desative o recorte
coord_cartesian(clip = "off")e faça engenharia reversa das coordenadas x, y a partir das coordenadas npc fornecidas antes de usarannotate. Isso é complicado, mas possível - Desenhe diretamente usando
grid. Isso é muito mais fácil, mas tem a desvantagem de que a anotação deve ser desenhada sobre o enredo em vez de fazer parte do próprio enredo. Você poderia fazer isso assim:
annotate_npc_abs <- function(label, x, y, ...)
{
grid::grid.draw(grid::textGrob(
label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}
E a sintaxe seria um pouco diferente:
p
annotate_npc_abs("hello", 0.05, 0.75)
A partir de 'ggpmisc' (> = 0.3.6), o código a seguir funciona conforme o esperado (no CRAN a partir de 2020-09-10).
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")