这里面涉及到的知识点包括两个,一个是ggplot2 对象的拼图(柱状图+分组图),以及如何按照指定的分组要求按照指定的顺序排序(大小)。
先加载包:
# 开始绘图
library(ggplot2)
library(patchwork)
library(RColorBrewer)
排序
首先看一下数据:
> dplyr::glimpse(mutation_number)
Rows: 8,640
Columns: 4
$ name <chr> "case1_biorep_A_techrep_1", "case1_biorep_A_tech…
$ type <chr> "case1", "case1", "case1", "case1", "case1", "ca…
$ counts <int> 542, 542, 542, 542, 542, 542, 542, 542, 542, 542…
$ mutation_type <fct> Missense_Mutation, Missense_Mutation, Frame_Shif…
先做一个最简单的柱状图:
p1 <- ggplot(data = mutation_number) +
geom_bar(mapping = aes(x = name, fill = mutation_type), position = "stack") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
p1 + theme(panel.background = element_rect(fill = NA),
plot.background = element_rect(fill = "antiquewhite1"),
legend.background = element_rect(fill = "transparent"))
如果想要对数据排序,则需要将指定数据列修改为factor 类型,接着通过指定levels,来设定顺序。
我们可以直接将排序后的内容作为levels :
mutation_number$name <- factor(mutation_number$name, levels = unique(mutation_number[order(mutation_number$counts),]$name))
也可以先定义好因子,接着再利用reorder 函数,将A 列按照B 列大小排序:
a <- mutation_number$name
mutation_number$name <- factor(mutation_number$name, levels = unique(mutation_number$name))
p1 <- ggplot(data = mutation_number) +
geom_bar(mapping = aes(x = reorder(name, counts), fill = mutation_type), position = "stack") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
p1 + theme(panel.background = element_rect(fill = NA),
plot.background = element_rect(fill = "antiquewhite1"),
legend.background = element_rect(fill = "transparent"))
这时候还是没有组间分组呀,本来是写的循环,将数据框按照指定类型列分组提取,接着将提取的结果排序:
# 这样还是不能实现组内排序,写个循环搞定
mutation_number_list_by_type <- list()
loop_count <- 1
for (x in unique(annotationDat$type)) {
tmp <- subset(mutation_number, type == x)
tmp$name <- factor(tmp$name)
tmp$name <- reorder(tmp$name, tmp$counts)
mutation_number_list_by_type[[loop_count]] <- tmp
loop_count = loop_count + 1
}
mutation_number_new <- do.call("rbind", mutation_number_list_by_type)
忽然发现这太笨啦,而且R 不喜欢循环;忽然注意到order 可以接受多个值,那我岂不是可以先按type 排序,再按count 排序?
# order 按照两列排序即可
tmp = mutation_number[order(mutation_number$type,mutation_number$counts),]
# 重新改一下levels 顺序
tmp$name <- factor(tmp$name, levels = unique(tmp$name))
ps:reorder 貌似不可以接受多行排序。
分组图和拼图
分组图实际也就是一个柱状图,我们把柱状图的各个边边角角,什么坐标轴呀,各种文字对象,只保留图和图例即可,其他统统去掉:
p2 <- ggplot(data = annotationDat, aes(x = name, y = 1)) + geom_tile(aes(fill = type)) +
scale_fill_manual(values = brewer.pal(6, "Set3")) + theme(panel.grid = element_blank(),
panel.background = element_blank(), axis.line = element_blank(),
axis.ticks.y = element_blank(), axis.text.y = element_blank(),
axis.title = element_blank(),
axis.text.x = element_text(angle = 90, hjust = 1))
拼图也很简单,将柱状图放在上面(将x 轴文字去除),将分组图放在下面,合理分配一下上下比例(height
参数):
p <- wrap_plots(p1, p2, nrow = 2, heights = c(11, 1))
p
其实不设定背景也还好看:
可能一些细节处的修改,可以后期查找各种ggplot 的内容慢慢打磨~
全部代码
# 排序
mutation_number_new <- mutation_number[order(mutation_number$type,mutation_number$counts),]
# 重新改一下levels 顺序
mutation_number_new$name <- factor(mutation_number_new$name, levels = unique(mutation_number_new$name))
# 画图
p1 <- ggplot(data = mutation_number_new) +
geom_bar(mapping = aes(x = name, fill = mutation_type), position = "stack") +
theme(axis.text.x=element_blank(),
axis.title.x=element_blank(),
axis.ticks.x=element_blank())
p1
p2 <- ggplot(data = annotationDat, aes(x = name, y = 1)) + geom_tile(aes(fill = type)) +
scale_fill_manual(values = brewer.pal(6, "Set3")) + theme(panel.grid = element_blank(),
panel.background = element_blank(), axis.line = element_blank(),
axis.ticks.y = element_blank(), axis.text.y = element_blank(),
axis.title = element_blank(),
axis.text.x = element_text(angle = 90, hjust = 1))
p2
p <- wrap_plots(p1, p2, nrow = 2, heights = c(11, 1))
p