这里面涉及到的知识点包括两个,一个是ggplot2 对象的拼图(柱状图+分组图),以及如何按照指定的分组要求按照指定的顺序排序(大小)。

先加载包:

  1. # 开始绘图
  2. library(ggplot2)
  3. library(patchwork)
  4. library(RColorBrewer)

排序

首先看一下数据:

  1. > dplyr::glimpse(mutation_number)
  2. Rows: 8,640
  3. Columns: 4
  4. $ name <chr> "case1_biorep_A_techrep_1", "case1_biorep_A_tech…
  5. $ type <chr> "case1", "case1", "case1", "case1", "case1", "ca
  6. $ counts <int> 542, 542, 542, 542, 542, 542, 542, 542, 542, 542
  7. $ mutation_type <fct> Missense_Mutation, Missense_Mutation, Frame_Shif

先做一个最简单的柱状图:

  1. p1 <- ggplot(data = mutation_number) +
  2. geom_bar(mapping = aes(x = name, fill = mutation_type), position = "stack") +
  3. theme(axis.text.x = element_text(angle = 90, hjust = 1))
  4. p1 + theme(panel.background = element_rect(fill = NA),
  5. plot.background = element_rect(fill = "antiquewhite1"),
  6. legend.background = element_rect(fill = "transparent"))

11. 将柱状图按照指定分组按大小排序 - 图1

如果想要对数据排序,则需要将指定数据列修改为factor 类型,接着通过指定levels,来设定顺序。

我们可以直接将排序后的内容作为levels :

  1. mutation_number$name <- factor(mutation_number$name, levels = unique(mutation_number[order(mutation_number$counts),]$name))

也可以先定义好因子,接着再利用reorder 函数,将A 列按照B 列大小排序:

  1. a <- mutation_number$name
  2. mutation_number$name <- factor(mutation_number$name, levels = unique(mutation_number$name))
  3. p1 <- ggplot(data = mutation_number) +
  4. geom_bar(mapping = aes(x = reorder(name, counts), fill = mutation_type), position = "stack") +
  5. theme(axis.text.x = element_text(angle = 90, hjust = 1))
  6. p1 + theme(panel.background = element_rect(fill = NA),
  7. plot.background = element_rect(fill = "antiquewhite1"),
  8. legend.background = element_rect(fill = "transparent"))

11. 将柱状图按照指定分组按大小排序 - 图2

这时候还是没有组间分组呀,本来是写的循环,将数据框按照指定类型列分组提取,接着将提取的结果排序:

  1. # 这样还是不能实现组内排序,写个循环搞定
  2. mutation_number_list_by_type <- list()
  3. loop_count <- 1
  4. for (x in unique(annotationDat$type)) {
  5. tmp <- subset(mutation_number, type == x)
  6. tmp$name <- factor(tmp$name)
  7. tmp$name <- reorder(tmp$name, tmp$counts)
  8. mutation_number_list_by_type[[loop_count]] <- tmp
  9. loop_count = loop_count + 1
  10. }
  11. mutation_number_new <- do.call("rbind", mutation_number_list_by_type)

忽然发现这太笨啦,而且R 不喜欢循环;忽然注意到order 可以接受多个值,那我岂不是可以先按type 排序,再按count 排序?

  1. # order 按照两列排序即可
  2. tmp = mutation_number[order(mutation_number$type,mutation_number$counts),]
  3. # 重新改一下levels 顺序
  4. tmp$name <- factor(tmp$name, levels = unique(tmp$name))

ps:reorder 貌似不可以接受多行排序。

11. 将柱状图按照指定分组按大小排序 - 图3

分组图和拼图

分组图实际也就是一个柱状图,我们把柱状图的各个边边角角,什么坐标轴呀,各种文字对象,只保留图和图例即可,其他统统去掉:

  1. p2 <- ggplot(data = annotationDat, aes(x = name, y = 1)) + geom_tile(aes(fill = type)) +
  2. scale_fill_manual(values = brewer.pal(6, "Set3")) + theme(panel.grid = element_blank(),
  3. panel.background = element_blank(), axis.line = element_blank(),
  4. axis.ticks.y = element_blank(), axis.text.y = element_blank(),
  5. axis.title = element_blank(),
  6. axis.text.x = element_text(angle = 90, hjust = 1))

11. 将柱状图按照指定分组按大小排序 - 图4

拼图也很简单,将柱状图放在上面(将x 轴文字去除),将分组图放在下面,合理分配一下上下比例(height 参数):

  1. p <- wrap_plots(p1, p2, nrow = 2, heights = c(11, 1))
  2. p

11. 将柱状图按照指定分组按大小排序 - 图5

其实不设定背景也还好看:

11. 将柱状图按照指定分组按大小排序 - 图6

可能一些细节处的修改,可以后期查找各种ggplot 的内容慢慢打磨~

全部代码

  1. # 排序
  2. mutation_number_new <- mutation_number[order(mutation_number$type,mutation_number$counts),]
  3. # 重新改一下levels 顺序
  4. mutation_number_new$name <- factor(mutation_number_new$name, levels = unique(mutation_number_new$name))
  5. # 画图
  6. p1 <- ggplot(data = mutation_number_new) +
  7. geom_bar(mapping = aes(x = name, fill = mutation_type), position = "stack") +
  8. theme(axis.text.x=element_blank(),
  9. axis.title.x=element_blank(),
  10. axis.ticks.x=element_blank())
  11. p1
  12. p2 <- ggplot(data = annotationDat, aes(x = name, y = 1)) + geom_tile(aes(fill = type)) +
  13. scale_fill_manual(values = brewer.pal(6, "Set3")) + theme(panel.grid = element_blank(),
  14. panel.background = element_blank(), axis.line = element_blank(),
  15. axis.ticks.y = element_blank(), axis.text.y = element_blank(),
  16. axis.title = element_blank(),
  17. axis.text.x = element_text(angle = 90, hjust = 1))
  18. p2
  19. p <- wrap_plots(p1, p2, nrow = 2, heights = c(11, 1))
  20. p