użyj jednostek NPC w annotate ()
Mam obiekt ggplot. Chciałbym dodać tekst z annotate(), a współrzędne tekstu chciałbym określić w jednostkach NPC. czy to możliwe?
Ten minimalny przykład pokazuje, jak tekst jest zwykle pozycjonowany za pomocą annotate():
library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + annotate("text", x = 30, y = 4.5, label = "hello")
Chciałbym osiągnąć ten sam efekt, ale zamiast określać xi ywe współrzędnych natywnych, chciałbym określić je za pomocą współrzędnych NPC. Na potrzeby tego przykładu nie przejmuję się dokładnym tłumaczeniem x = 30i y = 4.5na jednostki NPC. Chcę tylko wiedzieć, czy annotate()w ogóle można używać jednostek NPC .
Istnieją dwie powiązane strategie, ale nie są one całkowicie satysfakcjonujące:
Można używać jednostek NPC, określając je, mówią
grid::textGrob(). I wtedy można umieścić groba za pomocąannotation_custom(), jak w tej odpowiedzi @baptiste . Ale to rozwiązanie jest nieco bardziej uciążliwe, niż bym chciał.Pakiet "ggpmisc" zawiera
geom_text_npc(). Ale to jeszcze nie działa zannotate(). Oznacza to,annotate("text_npc", ...)że nie wydaje się działać. [Edytuj: teraz działa. Zobacz wiadomość Pedro Aphalo poniżej.]
Istnieje również wiele powiązanych postów. W szczególności Greg Snow zasugerował użycie siatki do utworzenia rzutni z wymiarami, pa następnie opisania tej rzutni. I @teunbrand zaproponował metodę, która pociąga za sobą konwersji pdo „gtable” obiektu (z ggplotGrob()), a następnie rysunek, który „gtable” obiekt. Każdą z tych strategii można prawdopodobnie dostosować do moich celów. Ale czy istnieje prostszy sposób używania współrzędnych NPC z annotate()?
Odpowiedzi
Osobiście użyłbym metody Baptiste, ale owiniętej w niestandardową funkcję, aby była mniej niezgrabna:
annotate_npc <- function(label, x, y, ...)
{
ggplot2::annotation_custom(grid::textGrob(
x = unit(x, "npc"), y = unit(y, "npc"), label = label, ...))
}
Co pozwala ci:
p + annotate_npc("hello", 0.5, 0.5)
Zauważ, że zawsze będzie to narysować twoją adnotację w przestrzeni NPC w rzutni każdego panelu na wykresie (tj. Względem szarego zacieniowanego obszaru, a nie całego okna kreślenia), co sprawia, że jest to przydatne dla aspektów. Jeśli chcesz narysować swoją adnotację w bezwzględnych współrzędnych NPC (więc masz możliwość kreślenia poza rzutnią panelu), masz dwie opcje:
- Wyłącz obcinanie za pomocą
coord_cartesian(clip = "off")i dokonaj inżynierii wstecznej współrzędnych x, y z podanych współrzędnych NPC przed użyciemannotate. To skomplikowane, ale możliwe - Narysuj go prosto za pomocą
grid. Jest to o wiele łatwiejsze, ale ma tę wadę, że adnotacja musi być narysowana na fabule, a nie być częścią samej fabuły. Możesz to zrobić w ten sposób:
annotate_npc_abs <- function(label, x, y, ...)
{
grid::grid.draw(grid::textGrob(
label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}
A składnia byłaby trochę inna:
p
annotate_npc_abs("hello", 0.05, 0.75)
Od „ggpmisc” (> = 0.3.6) następujący kod działa zgodnie z oczekiwaniami (w CRAN od 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")