简体   繁体   English

在图上方注释 ggplot

[英]annotate ggplot above plot

I tried lately to annotate a graph with boxes above a ggplot.我最近尝试用 ggplot 上方的框注释图形。 Here is what I want:这是我想要的:

在此处输入图片说明

I found a way using grid , but I find it too complicated, and I am quite sure there is a better way to do it, more ggplot2 friendly.我找到了一种使用grid的方法,但我觉得它太复杂了,我很确定有更好的方法来做到这一点,对ggplot2更友好。 Here is the example and my solution:这是示例和我的解决方案:

the data:数据:

y2 <- 350
mesure_pol <- data.frame(x1 = c(1,4,7),
                         x2 = c(4,7,10),
                         politiquecat = c(1:3),
                         politique = c("Phase 1\n","Phase 2\n","Phase 3\n"),
                         y = c(y2,y2,y2)
)
mesure_pol$x_median <- (mesure_pol$x1 + mesure_pol$x2)/2
colorpal <- viridis::inferno(n=3,direction = -1)

plot阴谋

the main plot主要情节

p <- ggplot(data = mesure_pol) +
  geom_rect(aes(xmin = x1,
                xmax = x2,
                ymin = 0,
                ymax = 300,
                fill = as.factor(politiquecat)),
            fill = colorpal,
            color = "black",
            size = 0.3,
            alpha = 0.2)+
  theme(plot.margin=unit(c(60, 5.5, 5.5, 5.5), "points"))+
  coord_cartesian(clip = 'off')

the annotation part注释部分

Here is the part I am not happy with:这是我不满意的部分:

for (i in 1:dim(mesure_pol)[1])  {
  
  text <- textGrob(label = mesure_pol[i,"politique"], gp = gpar(fontsize=7,fontface="bold"),hjust = 0.5)
  rg <- rectGrob(x = text$x, y = text$y, width = stringWidth(text$label) - unit(3,"mm") ,                 
                 height = stringHeight(text$label) ,gp = gpar(fill=colorpal[i],alpha = 0.3))
  p <- p + annotation_custom(
    grob = rg,
    ymin = mesure_pol[i,"y"],      # Vertical position of the textGrob
    ymax =  mesure_pol[i,"y"],    
    xmin = mesure_pol[i,"x_median"],         # Note: The grobs are positioned outside the plot area
    xmax = mesure_pol[i,"x_median"]) +
    annotation_custom(
      grob = text,
      ymin = mesure_pol[i,"y"],      # Vertical position of the textGrob
      ymax =  mesure_pol[i,"y"],    
      xmin = mesure_pol[i,"x_median"],         # Note: The grobs are positioned outside the plot area
      xmax = mesure_pol[i,"x_median"])
} 

Is there a simplier/nicer way to obtain similar result ?有没有更简单/更好的方法来获得类似的结果? I tried with annotate , label but without any luck.我尝试了annotatelabel但没有任何运气。

An alternative approach to achieve the desired result would be to make the annotations via a second ggplot which could be glued to the main plot via eg patchwork .实现所需结果的另一种方法是通过第二个 ggplot 进行注释,该注释可以通过例如patchwork粘贴到主图上。

For the annotation plot I basically used your code for the main plot, added a geom_text layer, get rid of the axix, etc. via theme_void and set the limits in line with main plot.对于注释图,我基本上将您的代码用于主图,添加了geom_text层,通过theme_void等,并根据主图设置了限制。 Main difference is that I restrict the y-axis to a 0 to 1 scale.主要区别在于我将 y 轴限制为 0 到 1 的比例。 Besides that I shifted the xmin, xmax, ymin and ymax values to add some space around the rectangels (therefore it is important to set the limits).除此之外,我移动了 xmin、xmax、ymin 和 ymax 值以在矩形周围添加一些空间(因此设置限制很重要)。

library(ggplot2)
library(patchwork)

y2 <- 350
mesure_pol <- data.frame(x1 = c(1,4,7),
                         x2 = c(4,7,10),
                         politiquecat = c(1:3),
                         politique = c("Phase 1\n","Phase 2\n","Phase 3\n"),
                         y = c(y2,y2,y2)
)
mesure_pol$x_median <- (mesure_pol$x1 + mesure_pol$x2)/2
colorpal <- viridis::inferno(n=3,direction = -1)

p <- ggplot(data = mesure_pol) +
  geom_rect(aes(xmin = x1,
                xmax = x2,
                ymin = 0,
                ymax = 300,
                fill = as.factor(politiquecat)),
            fill = colorpal,
            color = "black",
            size = 0.3,
            alpha = 0.2)

ann <- ggplot(data = mesure_pol) +
  geom_rect(aes(xmin = x1 + 1,
                xmax = x2 - 1,
                ymin = 0.2,
                ymax = 0.8,
                fill = as.factor(politiquecat)),
            fill = colorpal,
            color = "black",
            size = 0.3,
            alpha = 0.2) +
  geom_text(aes(x = x_median, y = .5, label = politique), vjust = .8, fontface = "bold", color = "black") +
  coord_cartesian(xlim = c(1, 10), ylim = c(0, 1)) +
  theme_void()

ann / p  + 
  plot_layout(heights = c(1, 4))

By setting a second x-axis and filling the background of the new axis labels with element_markdown from the ggtext package.通过设置第二个 x 轴并使用ggtext包中的element_markdown填充新轴标签的背景。 You may achieve this:你可以做到这一点:

在此处输入图片说明

Here is the code:这是代码:

library(ggtext)

y2 <- 350
mesure_pol <- data.frame(x1 = c(1,4,7),
                         x2 = c(4,7,10),
                         politiquecat = c(1:3),
                         politique = c("Phase 1\n","Phase 2\n","Phase 3\n"),
                         y = c(y2,y2,y2)
)
mesure_pol$x_median <- (mesure_pol$x1 + mesure_pol$x2)/2


p <- ggplot(data = mesure_pol) +
  geom_rect(aes(xmin = x1,
                xmax = x2,
                ymin = 0,
                ymax = 300,
                fill = as.factor(politiquecat)),
            fill = c("yellow", "red", "black"),
            color = "black",
            size = 0.3,
            alpha = 0.2) +
  scale_x_continuous(sec.axis = dup_axis(name = "",
                                         breaks = c(2.5, 5.5, 8.5),
                                         labels = c("Phase 1", "Phase 2", "Phase 3"))) +
  theme(plot.margin=unit(c(60, 5.5, 5.5, 5.5), "points"),
        axis.ticks.x.top = element_blank(),
        axis.text.x.top = element_markdown(face = "bold", 
                                  size = 12, 
                                  fill = adjustcolor(c("yellow", "red", "black"),
                                                              alpha.f = .2)))+
  coord_cartesian(clip = 'off')


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM