Home > Software engineering >  Annotation position does not work in faceted ggplot2 with inherit=FALSE
Annotation position does not work in faceted ggplot2 with inherit=FALSE

Time:08-19

I have a simple faceted plot from the following data

structure(list(Entity = c("Africa", "Americas", "Eastern Mediterranean", 
"Europe", "South-East Asia", "Western Pacific"), meandeaths = c(93.9, 
0.0821, 1.47, 0, 4.02, 0.569)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -6L))

I used the code here to add a single annotation at the bottom of the plot. Unfortunately, the annotation appears in each of the facets, although I have used inherit = TRUE in the aes.

library(ggfittext) library(ggtext) library(extrafont) library(extrafontdb) library(tidyverse)

plot_label <- 'Africa is the world region that is most affected by malaria: in 2019, 96% of global deaths from malaria occurred on the African continent.' %>% 
    str_wrap(width = 50)
   
   
     colors_palette <- c(
    "Africa"= "#01FF70", 
    "Americas" = "#FFDC00", 
    "Eastern Mediterranean" = "#FF851B", 
    "South-East Asia" = "#F012BE",
    "Western Pacific" = "red",
     "Europe" = "skyblue")
    
   common_theme <- function() {
    theme_minimal()   
     theme(
      text = element_text(color = "#FFFFFF"),
      strip.text = element_blank(), 
      axis.text = element_blank(), 
      axis.title = element_blank(),
      panel.grid = element_blank(),
      plot.title = element_markdown(family = "Century Gothic", size = rel(7.5), face = "bold",  color = "#EF476F", hjust = .5, margin = margin(t = 1,b = 1, unit = "cm")),
      plot.subtitle = element_markdown(size = rel(3), face = "bold", family = "Century Gothic",  hjust = .5, margin = margin(t = .25, b = .25, unit = "cm")), 
      plot.background = element_rect(fill = "#111111", color = NA)
     )
   }
   

plotmal %>%   
     mutate(Entity = as.factor(Entity)) %>%  
    
     ggplot(aes(x = 3, fill = Entity))   
     geom_col(
      aes(y= meandeaths),
      color = NA
     )   
     geom_col(
      aes(y = 1),
      alpha = .35, 
      color = NA
     )   
     ggtext::geom_richtext(
      aes(.2, 0, 
          label = glue::glue("<span style ='font-size: 35px;'>{str_to_title(Entity)}</span><br><span style='font-size:27.5px;'>{round(meandeaths,2)}%</span>"),
          color = Entity
      ),
      family = "Century Gothic",
      fill = NA,
      label.size = 0, 
      label.color = NA,
      lineheight = 1.5
     )   
     
     annotate(geom ="text", x = 1.2, y =-1.5, label = plot_label, 
             size = 4.5, family = "Century Gothic" ,fontface = "italic", color = "#FFFFFF", lineheight = .95,inherit.aes = FALSE 
     
     )  # inherit.aes = FALSE does not work
     
     labs(
      title = "Silent Killer",
      subtitle = "Global Malaria Deaths by Region 2000-2020",
      caption = "Data:OurWorldinData | Viz: @stepminer2"
     )  
     scale_x_continuous(
      limits = c(0.2, 3   0.5)  
     )  
     scale_fill_manual(
      values = colors_palette,
      guide = "none"
     )   
     scale_color_manual(
      values = colors_palette,
      guide = "none"
     )   
     coord_polar(theta = "y")   
     facet_wrap(vars(Entity), nrow = 2)   
     common_theme()  
     theme(
      plot.margin = margin(t = .5,b = 1, unit = "cm")
     )
     

How can I solve this problem?

CodePudding user response:

Unfortunately ggplot2::annotate or ggplot2::annotation_custom will add to each facet and using inherit=FALSE will not change that.

But one option to overcome this would be the gggrid package which unlike ggplot2::annotate or ggplot2::annotation_custom allows for placing different grobs on each facet or as in your case to place a label on only one facet. To this end:

  1. Create your label as a textGrob which also allows to use relative coordinates to place your label.
  2. Add this label to your plot via gggrid::grid_panel. Here you could pass a data.frame to the data argument which contains only an Entity column and which is used to specify the panels where you want to add the label, i.e. in your case "Europe".
tg <- grid::textGrob(plot_label,
  x = unit(0, "npc")   unit(2, "mm"),
  y = unit(0, "npc")   unit(2, "mm"),
  just = c("left", "bottom"),
  gp = grid::gpar(fontsize = 4.5 * .pt, fontfamily = "Century Gothic", col = "#FFFFFF", lineheight = .95)
)


plotmal %>%
  mutate(Entity = as.factor(Entity)) %>%
  ggplot(aes(x = 3, fill = Entity))  
  geom_col(
    aes(y = meandeaths),
    color = NA
  )  
  geom_col(
    aes(y = 1),
    alpha = .35,
    color = NA
  )  
  ggtext::geom_richtext(
    aes(.2, 0,
      label = glue::glue("<span style ='font-size: 35px;'>{str_to_title(Entity)}</span><br><span style='font-size:27.5px;'>{round(meandeaths,2)}%</span>"),
      color = Entity
    ),
    family = "Century Gothic",
    fill = NA,
    label.size = 0,
    label.color = NA,
    lineheight = 1.5
  )  
  labs(
    title = "Silent Killer",
    subtitle = "Global Malaria Deaths by Region 2000-2020",
    caption = "Data:OurWorldinData | Viz: @stepminer2"
  )  
  scale_x_continuous(
    limits = c(0.2, 3   0.5)
  )  
  scale_fill_manual(
    values = colors_palette,
    guide = "none"
  )  
  scale_color_manual(
    values = colors_palette,
    guide = "none"
  )  
  coord_polar(theta = "y")  
  facet_wrap(vars(Entity), nrow = 2)  
  common_theme()  
  theme(
    plot.margin = margin(t = .5, b = 1, unit = "cm")
  )  
  gggrid::grid_panel(tg, data = data.frame(Entity = "Europe"))

enter image description here

UPDATE If you want your annotation to span the whole width of the plot I would go for a patchwork approach where the annotation is created as a second plot and glued to the main plot.

Note: For the annotation plot I use geom_textbox. I also dropped the str_wrap which IMHO does not make any sense in this case.

p_main <- plotmal %>%
  mutate(Entity = as.factor(Entity)) %>%
  ggplot(aes(x = 3, fill = Entity))  
  geom_col(
    aes(y = meandeaths),
    color = NA
  )  
  geom_col(
    aes(y = 1),
    alpha = .35,
    color = NA
  )  
  ggtext::geom_richtext(
    aes(.2, 0,
      label = glue::glue("<span style ='font-size: 35px;'>{str_to_title(Entity)}</span><br><span style='font-size:27.5px;'>{round(meandeaths,2)}%</span>"),
      color = Entity
    ),
    family = "Century Gothic",
    fill = NA,
    label.size = 0,
    label.color = NA,
    lineheight = 1.5
  )  
  scale_fill_manual(
    values = colors_palette,
    guide = "none"
  )  
  scale_color_manual(
    values = colors_palette,
    guide = "none"
  )  
  coord_polar(theta = "y")  
  facet_wrap(vars(Entity), nrow = 2)  
  common_theme()

p_anno <- ggplot(data.frame(x = factor(1), y = factor(1)), aes(x = x, y = y))  
  geom_textbox(label = plot_label, color = "white", fill = "#111111", lineheight = .95, 
               family = "Century Gothic", size = 4.5, width = unit(1, "npc"), box.colour = NA,
               halign = .5)  
  common_theme()  
  theme(
    plot.margin = margin(t = .5, b = 1, unit = "cm")
  )

library(patchwork)

p_main / p_anno   plot_layout(heights = c(20, 1)) &
  plot_annotation(
    title = "Silent Killer",
    subtitle = "Global Malaria Deaths by Region 2000-2020",
    caption = "Data:OurWorldinData | Viz: @stepminer2",
    theme = common_theme()
  )

enter image description here

  • Related