查看原文
其他

ggplot2绘图进阶:如何在不同分面添加不同图形

JunJunLab R语言统计与绘图 2023-05-21

本文转载自‍老俊俊的生信笔记 公众号

1引言

有时候我们可能想在不同不同的分面添加不同的内容,比如文字,图形等等,今天分享一下如何在不同分面添加对应的图形进去

参考链接:

一个兄弟的在线笔记,我们来学习一下:

https://clarewest.github.io/blog-posts/ggplotInset.html

2绘图

整理数据:

library(ggplot2)   ## for plotting
library(dplyr)     ## for data manipulation
library(lubridate) ## for handling dates

nobel <- read.csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-05-14/nobel_winners.csv")
plot_data <-
  nobel %>%
  mutate(prize_date = paste0(prize_year, "-12-10"),
         age = time_length(interval(ymd(birth_date), ymd(prize_date)), "year")) %>%
  group_by(prize_year, laureate_id) %>%
  slice(1) %>%  ## make sure we have just one row per prizewinner per year
  ungroup()

分面绘图:

main_plot <-
  ggplot(plot_data, aes(group=category)) +
  geom_point(aes(x=prize_year, y=age, colour=gender), alpha=0.6) +
  facet_wrap(~category) +  ## plot each prize category separately
  theme_bw() +
  labs(y="Age of prize winner", x="Year of award") +
  geom_smooth(aes(x=prize_year, y=age), method = "loess") + ## add a smoothed line
  scale_y_continuous(limits=c(0,100)) +
  scale_colour_discrete(breaks=c("Female","Male")) +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "bottom",
        legend.title = element_blank())

main_plot

绘制插入的图形:

## A function to plot the inset
get_inset <- function(df){
  p <- ggplot(data=df %>%
                group_by(category, prize_year) %>%
                slice(1),
              aes(x=prize_share, fill=category)) +
    geom_bar() +
    scale_x_discrete( drop=FALSE) +
    scale_fill_manual(values = c("#00BF7D""#A3A500""#F8766D","#00B0F6","#E76BF3","#636363")) +
    guides(fill=FALSE) +
    theme_bw(base_size=9) +  ## makes everything smaller
    theme(panel.background = element_rect(fill="white"),  ## white plot background
          axis.title.y = element_blank(),
          axis.title.x = element_blank(),
          axis.text.x = element_text(size=rel(0.7)), ## tiny axis text
          panel.grid.major = element_blank(),
          panel.grid.minor = element_blank(),
          plot.background = element_blank())
  return(p)
}

inset_plot <- get_inset(plot_data)

inset_plot

给分面插入图形:

## Add it as an inset
main_plot +
    annotation_custom(grob=ggplotGrob(inset_plot),
                      ymin = -8, ymax=34, xmin=1955, xmax=2015)

可以看到每个分面插入了一模一样的图形,并不是我们想要的结果。

重新定义 annotation_custom 函数:

## This function allows us to specify which facet to annotate
annotation_custom2 <- function (grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, data)
{
  layer(data = data, stat = StatIdentity, position = PositionIdentity,
        geom = ggplot2:::GeomCustomAnn,
        inherit.aes = TRUE, params = list(grob = grob,
                                          xmin = xmin, xmax = xmax,
                                          ymin = ymin, ymax = ymax))
}

指定特定的分面进行插入:

main_plot +
    annotation_custom2(grob=ggplotGrob(inset_plot),
                      data = data.frame(category="Chemistry"),
                      ymin = -8, ymax=34, xmin=1955, xmax=2015)

这里关键的代码是 **data = data.frame(category="Chemistry")**。

批量插入:

library(purrr)

insets <- plot_data %>%
  split(f = .$category) %>%
  purrr::map(~annotation_custom2(
    grob = ggplotGrob(get_inset(.) +
                        scale_y_continuous(limits=c(0,105), breaks = c(050100))),
    data = data.frame(category=unique(.$category)),
    ymin = -8, ymax=34, xmin=1955, xmax=2015)
  )


main_plot + insets

看起来好像没问题了。

3结尾

一天一个小技能。


关注下方公众号,分享更多更好玩的R语言知识。

点个在看,SCI马上发表。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存