在 annotate() 中使用 npc 单位

use*_*473 2 grid r coordinates ggplot2 ggpmisc

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

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

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

我想达到相同的效果,但不是在本地坐标中指定xy,我想用 npc 坐标指定它们。出于本示例的目的,我并不担心准确地转换x = 30y = 4.5转换为 npc 单位。我只是想知道是否可以使用npc单位annotate()

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

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

  2. “ggpmisc”包包括geom_text_npc(). 但它还不适用于annotate(). 也就是说,annotate("text_npc", ...)似乎不起作用。[编辑:它现在可以工作了。见下面佩德罗·阿法洛的消息。]

还有很多相关的帖子。特别是,Greg Snow 建议使用网格创建一个具有 尺寸的p视口,然后注释该视口。并且@teunbrand 提出了一种方法,该方法需要转换p为“gtable”对象(使用ggplotGrob()),然后绘制该“gtable”对象。这些策略中的任何一个都可能适合我的目的。但是有没有更直接的方法来使用 npc 坐标annotate()

All*_*ron 6

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

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

这允许您执行以下操作:

p + annotate_npc("hello", 0.5, 0.5)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

请注意,这将始终在绘图中每个面板的视口的 npc 空间中绘制您的注释(即相对于灰色阴影区域而不是整个绘图窗口),这使得它对于刻面非常方便。如果您想在绝对 npc 坐标中绘制注释(因此您可以选择在面板视口之外绘图),您的两个选项是:

  1. 关闭剪下带coord_cartesian(clip = "off")和反向使用前工程师在x,从给定的NPC坐标y坐标annotate。这很复杂但可能
  2. 直接使用grid. 这要容易得多,但有一个缺点,即注释必须绘制在图上,而不是图本身的一部分。你可以这样做:
annotate_npc_abs <- function(label, x, y, ...) 
{
  grid::grid.draw(grid::textGrob(
    label, x = unit(x, "npc"), y = unit(y, "npc"), ...))
}
Run Code Online (Sandbox Code Playgroud)

语法会有点不同:

p 
annotate_npc_abs("hello", 0.05, 0.75)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明