Verwenden Sie NPC-Einheiten in annotate ()
Ich habe ein ggplot-Objekt. Ich möchte Text hinzufügen annotate()und die Koordinaten des Textes in NPC-Einheiten angeben. Ist das möglich?
Dieses minimale Beispiel zeigt, wie Text normalerweise positioniert wird mit annotate():
library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + annotate("text", x = 30, y = 4.5, label = "hello")
Ich möchte den gleichen Effekt erzielen, aber anstatt anzugeben xund yin nativen Koordinaten, möchte ich sie mit npc-Koordinaten angeben. Für die Zwecke dieses Beispiels, bin ich besorgt nicht um genau zu übersetzen x = 30und y = 4.5in npc Einheiten. Ich möchte nur wissen, ob NPC-Einheiten überhaupt verwendet werden annotate()können.
Es gibt zwei verwandte Strategien, die jedoch nicht ganz zufriedenstellend sind:
Man kann NPC-Einheiten verwenden, indem man sie beispielsweise wie folgt spezifiziert
grid::textGrob(). Und man kann dann den Grob mit platzierenannotation_custom(), wie in dieser Antwort von @baptiste . Aber diese Lösung ist etwas umständlicher als ich es gerne hätte.Das "ggpmisc" -Paket enthält
geom_text_npc(). Aber es funktioniert noch nicht mitannotate(). Das heißt,annotate("text_npc", ...)scheint nicht zu funktionieren. [Bearbeiten: es funktioniert jetzt. Siehe Pedro Aphalos Nachricht unten.]
Es gibt auch viele verwandte Beiträge. Insbesondere hat Greg Snow vorgeschlagen, mithilfe eines Rasters ein Ansichtsfenster mit den Abmessungen pdieses Ansichtsfensters zu erstellen und dieses anschließend mit Anmerkungen zu versehen. Und @teunbrand hat eine Methode vorgeschlagen, bei der pin ein "gtable" -Objekt (mit ggplotGrob()) konvertiert und dann dieses "gtable" -Objekt gezeichnet wird. Jede dieser Strategien kann wahrscheinlich an meine Zwecke angepasst werden. Aber gibt es eine einfachere Möglichkeit, NPC-Koordinaten mit zu verwenden annotate()?
Antworten
Persönlich würde ich Baptistes Methode verwenden, aber in eine benutzerdefinierte Funktion eingebunden, um sie weniger klobig zu machen:
annotate_npc <- function(label, x, y, ...)
{
ggplot2::annotation_custom(grid::textGrob(
x = unit(x, "npc"), y = unit(y, "npc"), label = label, ...))
}
Was Ihnen erlaubt:
p + annotate_npc("hello", 0.5, 0.5)
Beachten Sie, dass Ihre Annotation immer im NPC-Bereich des Ansichtsfensters jedes Panels im Plot gezeichnet wird (dh relativ zum grau schattierten Bereich und nicht zum gesamten Plotfenster), was es für Facetten praktisch macht. Wenn Sie Ihre Anmerkung in absoluten NPC-Koordinaten zeichnen möchten (Sie haben also die Möglichkeit, außerhalb des Ansichtsfensters des Bedienfelds zu zeichnen), haben Sie zwei Möglichkeiten:
- Schalten Sie das Abschneiden mit aus
coord_cartesian(clip = "off")und konstruieren Sie die x, y-Koordinaten von den angegebenen npc-Koordinaten zurück, bevor Sie sie verwendenannotate. Das ist kompliziert aber möglich - Zeichnen Sie es direkt mit
grid. Dies ist weitaus einfacher, hat jedoch den Nachteil, dass die Anmerkung über das Diagramm gezogen werden muss, anstatt Teil des Diagramms selbst zu sein. Sie könnten das so machen:
annotate_npc_abs <- function(label, x, y, ...)
{
grid::grid.draw(grid::textGrob(
label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}
Und die Syntax wäre etwas anders:
p
annotate_npc_abs("hello", 0.05, 0.75)
Ab 'ggpmisc' (> = 0.3.6) funktioniert der folgende Code wie erwartet (in CRAN ab 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")