在 annotate() 中使用 npc 单位

use npc units in annotate()

我有一个 ggplot 对象。我想用 annotate() 添加一些文本,我想以 npc 单位指定文本的坐标。这可能吗?

这个最小的例子演示了文本通常如何定位 annotate():

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

我想达到同样的效果,但是我不想在本地坐标中指定xy,而是用npc坐标指定它们。出于本示例的目的,我并不担心将 x = 30y = 4.5 准确翻译成 npc 单位。我只想知道annotate()能不能用npc单位

有两个相关策略,但它们并不完全令人满意:

  1. 可以通过将 npc 单位指定为 grid::textGrob() 来使用它们。然后可以用 annotation_custom() 放置 grob,如 。但是这个解决方案比我想要的要麻烦一些。

  2. “ggpmisc”包包括 geom_text_npc()。但是它 doesn't yet workannotate()。也就是说,annotate("text_npc", ...) 似乎不起作用。 [编辑:现在有效。请参阅下面 Pedro Aphalo 的消息。]

还有很多相关的帖子。特别是,Greg Snow has suggested using grid to create a viewport with the dimensions of p and then annotating that viewport. And 一种需要将 p 转换为“gtable”对象(使用 ggplotGrob())然后绘制该“gtable”对象的方法。这些策略中的任何一个都可能适合我的目的。但是有没有更直接的方法来使用 npc 坐标 annotate()?

就个人而言,我会使用 Baptiste 的方法,但包含在自定义函数中以使其不那么笨拙:

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

这允许你做:

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

请注意,这将始终在绘图中每个面板的视口的 npc space 中绘制您的注释(即相对于灰色阴影区域而不是整个绘图 window)使它对切面很方便。如果你想在绝对 npc co-ordinates 中绘制你的注释(所以你可以选择在面板视口之外绘制),你的两个选择是:

  1. 使用 coord_cartesian(clip = "off") 关闭裁剪并在使用 annotate 之前从给定的 npc co-ordinates 反向工程 x,y co-ordinates。这是
  2. 使用 grid 直接画出来。这要容易得多,但缺点是注释必须绘制在图上而不是图本身的一部分。你可以这样做:
annotate_npc_abs <- function(label, x, y, ...) 
{
  grid::grid.draw(grid::textGrob(
    label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}

语法会有点不同:

p 
annotate_npc_abs("hello", 0.05, 0.75)

从 'ggpmisc'(>=0.3.6)开始,以下代码按预期工作(在 2020-09-10 的 CRAN 中)。

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