Verwenden Sie NPC-Einheiten in annotate ()

Sep 04 2020

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:

  1. Man kann NPC-Einheiten verwenden, indem man sie beispielsweise wie folgt spezifiziert grid::textGrob(). Und man kann dann den Grob mit platzieren annotation_custom(), wie in dieser Antwort von @baptiste . Aber diese Lösung ist etwas umständlicher als ich es gerne hätte.

  2. Das "ggpmisc" -Paket enthält geom_text_npc(). Aber es funktioniert noch nicht mit annotate(). 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

6 AllanCameron Sep 04 2020 at 20:31

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:

  1. 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 verwenden annotate. Das ist kompliziert aber möglich
  2. 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)

1 PedroAphalo Sep 11 2020 at 00:20

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