ggplot2 - 在情节之外进行注释

Posted

技术标签:

【中文标题】ggplot2 - 在情节之外进行注释【英文标题】:ggplot2 - annotate outside of plot 【发布时间】:2012-09-06 18:13:24 【问题描述】:

我想将样本大小值与绘图上的点相关联。我可以使用geom_text 将数字定位在点附近,但这很麻烦。沿着情节的外边缘排列它们会更干净。

例如,我有:

df=data.frame(y=c("cat1","cat2","cat3"),x=c(12,10,14),n=c(5,15,20))

ggplot(df,aes(x=x,y=y,label=n))+geom_point()+geom_text(size=8,hjust=-0.5)

这会产生这个情节:

我更喜欢这样的:

我知道我可以创建第二个绘图并使用grid.arrange(如this post),但确定 textGrob 的间距以与 y 轴对齐会很繁琐。有没有更简单的方法来做到这一点?谢谢!

【问题讨论】:

这可以通过辅助轴来完成,我认为它正在开发中。但如果你想试试看这个链接groups.google.com/forum/?fromgroups=#!topic/ggplot2/_3Pm-JEoCqE 嗯,很有趣...我想知道 Hadley 是否会实现这一点。但是,我在尝试加载 devtools: call: if (!version_match) error: argument is of length zero 时遇到了一些奇怪的错误。 我只能说 devtools 对我有用。如果您无法解决问题,您应该尝试发布问题。 我通过在 CRAN 上安装 .zip 中的 ggplot2 0.9.2.1 来解决这个问题。现在@LucianoSelzer 在链接中提供的代码没有运行(guide_axis 的多个参数)。也许今晚太多了?我会睡在上面,看看我早上能不能弄明白 另见***.com/a/17493256/471093 【参考方案1】:

现在这在 ggplot2 3.0.0 中很简单,因为现在可以通过在坐标函数(例如 coord_cartesian(clip = 'off')coord_fixed(clip = 'off'))中使用 clip = 'off' 参数来禁用绘图中的裁剪。下面是一个示例。

    # Generate data
    df <- data.frame(y=c("cat1","cat2","cat3"),
                     x=c(12,10,14),
                     n=c(5,15,20))

    # Create the plot
    ggplot(df,aes(x=x,y=y,label=n)) +
      geom_point()+
      geom_text(x = 14.25, # Set the position of the text to always be at '14.25'
                hjust = 0,
                size = 8) +
      coord_cartesian(xlim = c(10, 14), # This focuses the x-axis on the range of interest
                      clip = 'off') +   # This keeps the labels from disappearing
      theme(plot.margin = unit(c(1,3,1,1), "lines")) # This widens the right margin

【讨论】:

这绝对是最简单的选择,谢谢! @ktyagi 也许您现在已经对此进行了排序,但是您将使用完全相同的参数,但指定 ylimxlim 为了完整起见,clip = off 也可以称为@coord_flip(我也假设为 coord_x)。添加coord_cartesian(clip = 'off') 对我来说不是解决方案,因为我需要coord_flip 这很好,谢谢@LeroyTyrone。我刚刚更新了答案以反映这一点。 值得注意的是,这似乎不适用于coord_polar 如果x轴有日期,有谁知道代码应该是怎样的?我正在尝试使用 as.Date("2020-09-01") 但收到消息“as.Date() 中的错误:必须提供'origin'”【参考方案2】:

您不需要绘制第二个图。您可以使用 annotation_custom 将 grobs 定位在绘图区域内部或外部的任何位置。 grobs 的定位是根据数据坐标进行的。假设“5”、“10”、“15”与“cat1”、“cat2”、“cat3”对齐,则需要注意 textGrobs 的垂直定位 - 您的三个 textGrob 的 y 坐标由三个数据点的 y 坐标。默认情况下,ggplot2 剪切到绘图区域,但可以覆盖剪切。相关边际需要扩大,以便为 grob 腾出空间。以下(使用 ggplot2 0.9.2)给出了一个类似于你的第二个图的图:

library (ggplot2)
library(grid)

df=data.frame(y=c("cat1","cat2","cat3"),x=c(12,10,14),n=c(5,15,20))

p <- ggplot(df, aes(x,y)) + geom_point() +            # Base plot
     theme(plot.margin = unit(c(1,3,1,1), "lines"))   # Make room for the grob

for (i in 1:length(df$n))  
p <- p + annotation_custom(
      grob = textGrob(label = df$n[i], hjust = 0, gp = gpar(cex = 1.5)),
      ymin = df$y[i],      # Vertical position of the textGrob
      ymax = df$y[i],
      xmin = 14.3,         # Note: The grobs are positioned outside the plot area
      xmax = 14.3)
     

# Code to override clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

【讨论】:

在x=Inf,hjust>=1处有一个geom_text层,关闭裁剪不是更简单吗? @jslefche,您应该注意@baptiste 提供的解决方案要简单得多。 p = p + geom_text(aes(label = n, x = Inf, y = y), hjust = -1)。然后关闭剪辑。虽然对齐可能会稍微偏离。 如何关闭剪辑? @ThomasBrowne 要关闭剪辑,请参见上面的最后三行代码。 不幸的是,您需要放置文本的 x 位置随 x 轴的范围而变化。因此,您需要使用相对于轴范围的 x 值。这是我的解决方案。我用xlim.range &lt;- ggplot_build(plot)$panel$ranges[[1]]$x.range 得到 x ggplot 计算轴范围。然后我将它用作 x 位置:x = xlim.range[1] - diff(xlim.range)/10 并且它有效!【参考方案3】:

基于grid的更简单的解决方案

require(grid)

df = data.frame(y = c("cat1", "cat2", "cat3"), x = c(12, 10, 14), n = c(5, 15, 20))

p <- ggplot(df, aes(x, y)) + geom_point() + # Base plot
theme(plot.margin = unit(c(1, 3, 1, 1), "lines"))

p

grid.text("20", x = unit(0.91, "npc"), y = unit(0.80, "npc"))
grid.text("15", x = unit(0.91, "npc"), y = unit(0.56, "npc"))
grid.text("5", x = unit(0.91, "npc"), y = unit(0.31, "npc"))

【讨论】:

简单得多,乍一看,但是...字体与 ggplot2 默认值不匹配,因此您必须摆弄这些设置,并且由于使用 npc 单位而更难定位文本。最终可能同样复杂。

以上是关于ggplot2 - 在情节之外进行注释的主要内容,如果未能解决你的问题,请参考以下文章

情节推翻了ggplot2的scale_fill_manual的标签

ggplot2,更改标题大小

R:ggplot2,我可以将情节标题设置为环绕并缩小文本以适应情节吗?

裁剪出情节周围的 ggplot2 空白

R语言ggplot2可视化:ggplot2使用geom_mark_ellipse函数进行椭圆形圈定(注释)特定的数据簇或组

如何使 ggplot2 中的图例与我的情节高度相同?