单组火山图和多组火山图展示差异表达基因(DEGs) 2023-10-12

前言

在各种RNA测序数据中,我们几乎都避不开差异表达基因(DEGs)的分析。我们可以用气泡图,提琴图和热图等展示不同细胞亚群或样本的差异基因表达情况,而火山图则是最直观的表现形式之一,因此本文将介绍画火山图的作图。

单组火山图
单组火山图

这是比较常见的火山图,但只能展示两组的差异基因。
函数示例:

deg_volcano_plot(all_markers,label='out',fc.filter=1.5,p.val=0.01, wt='avg_log2FC',gene.col='gene',lb.filter=2)

deg_volcano_plot函数的参数:
all_markers 包含显著性,差异倍数,基因名的数据框,可由Seurat的FindAllmarkers或FindMarkers得到
label='out' ,输出文件的前缀。
fc.filter=1.5 ,展示的基因点FC阈值
p.val=0.01,显著性阈值
wt='avg_log2FC' ,差异倍数的列名
gene.col='gene',基因名所在列名
lb.filter=2,标记基因名的FC阈值

library(dplyr)
library(ggplot2)
library(stringr)
library(data.table)
deg_volcano_plot <- function(all_markers,label='out',fc.filter=1.5,p.val=0.01, wt='avg_log2FC',gene.col='gene',lb.filter=2){
try({
  a <- all_markers
  a$gene <- a[,gene.col]
  a$logfc <- a[,wt]
  if (wt=='avg_log2FC'){
  a$FC<-2^a$logfc
  }else{
  a$FC<-exp(a$logfc)
  }
  a$log2FC <- log2(a$FC)
  a_h<-a[a$FC>=fc.filter & a$p_val_adj<=p.val,]
  a_l<-a[a$FC<1/fc.filter & a$p_val_adj<p.val,]

  gene_list <- c(a_h$gene, a_l$gene)
  a_all<-rbind(a_h,a_l)
  pos<- a$gene %in% a_all$gene
  a_no<-a[!pos,]
  try(a_h$type<-"Up")
  try(a_l$type<-"Down")
  try(a_no$type<-"None")
  a_all<-rbind(a_h,a_no,a_l)
  mat<-a_all
  ran<-runif(nrow(a_all),min = 25,max =50)
  ran<-100^-ran
  mat$p_val_adj<-mat$p_val_adj+ran
  cdn <- which(mat$gene %in% gene_list)
  mat1 <- mat[cdn,]
pdf(paste0(label,"_vocalno_plot_",".pdf"),12,12)
  p1<-ggplot(mat,aes(log2(FC),-1*log10(p_val_adj)))+
            geom_point(aes(color =type))+
            geom_text_repel(data=subset(mat1, abs(mat1$log2FC) >=log2(lb.filter)),aes(x=log2(FC),y=-log10(p_val_adj),label=gene),size=5,point.padding = 0.5)+
            scale_color_manual(values=c('#377EB8',"lightgrey",'#E41A1C'))+
            theme(panel.background =element_blank(),axis.line=element_line(colour="black"))

  p1<-p1+theme(legend.title=element_blank(),legend.background = element_blank(),legend.key = element_blank(), legend.text = element_text(size=20), legend.position="NA")
  p1<-p1+theme_bw()+theme(axis.text = element_text(size = 20))
  p1<-p1+geom_vline(xintercept=c(-1,1),lty=3,col="black",lwd=0.8)+geom_hline(yintercept = -log10(0.01),lty=3,col="black",lwd=0.8)
  p1<-p1+ggtitle(label)+theme(plot.title = element_text(hjust = 0.5,size=30,face="bold"))+theme(axis.title =element_text(size=20))
  print(p1)
dev.off()
})
}

多组火山图

多组火山图

相比于前者可以展示多组的差异基因,plot_mutideg函数理论上也能画单组火山图。
函数使用示例:

plot_mutideg(df,incluster='cluster',infc='avg_log2FC',ingene='gene',pos=TRUE,prefix='out',mycol <- c("#E64B357F","#4DBBD57F","#00A0877F","#3C54887F","#F39B7F7F","#8491B47F","#91D1C27F","#DC00007F","#7E61487F"))

plot_mutideg函数的参数:
df 包含显著性,差异倍数,基因名的数据框,可由Seurat的FindAllmarkers得到
incluster,默认为cluster,分组的列名
infc,默认为avg_log2FC,差异倍数所在列名
ingene,默认为gene,基因名所在列名,
pos,默认为TRUE,是否只展示上调基因,
prefix='out',输出文件的前缀
mycol,默认为NULL,调色板,颜色数目需多于分组的数目。

library(ggplot2)
library(tidyverse)
library(ggrepel)
plot_mutideg <- function(df,incluster='cluster',infc='avg_log2FC',ingene='gene',pos=TRUE,prefix='out',
                         mycol=NULL){
df$cluster=unlist(df[incluster])
df$avg_log2FC=unlist(df[infc])
df$gene=unlist(df[ingene])
df$label <- ifelse(df$p_val_adj<0.01,"adjust P-val<0.01","adjust P-val>=0.01")
top10sig <- df %>% group_by(cluster) %>% top_n(10,wt=avg_log2FC)
df$size <- case_when(!(df$gene %in% top10sig$gene)~ 1,
                     df$gene %in% top10sig$gene ~ 2)
dt <- filter(df,size==1)

b1 <- top10sig %>% group_by(cluster) %>% summarize(bar = max(avg_log2FC,na.rm = T))
b2 <- top10sig %>% group_by(cluster) %>% summarize(bar = min(avg_log2FC,na.rm = T))

lsed= c(1:length(unique(df$cluster)))-1
dfbar<-data.frame(x=lsed,
                  y=b1$bar)
dfbar1<-data.frame(x=lsed,
                   y=b2$bar)
iny=0
if (pos){
p1 <- ggplot()+
geom_col(data = dfbar,
         mapping = aes(x = x,y = y),
         fill = "#dcdcdc",alpha = 0.6)
iny=-0.5
}else{
p1 <- ggplot()+
geom_col(data = dfbar,
         mapping = aes(x = x,y = y),
         fill = "#dcdcdc",alpha = 0.6)+
geom_col(data = dfbar1,
         mapping = aes(x = x,y = y),
         fill = "#dcdcdc",alpha = 0.6)
}

p2 <- p1+
geom_jitter(data = dt,
            aes(x = cluster, y = avg_log2FC, color = label),
            size = 0.85,
            width =0.4)+
geom_jitter(data = data.frame(top10sig),
            aes(x = cluster, y = avg_log2FC, color = label),
            size = 1,
            width =0.4,
            shape=17)

dfcol<-data.frame(x=lsed,
                  y=iny,
                  label=unique(df$cluster))
p3 <- p2 + geom_tile(data = dfcol,
                     aes(x=x,y=y),
                     height=0.4,
                     color = "black",
                     fill = mycol,
                     alpha = 0.6,
                     show.legend = F)

p4 <- p3+
geom_text_repel(
                data=top10sig,
                aes(x=cluster,y=avg_log2FC, label=gene),
                force = 1.2,
                arrow = arrow(length = unit(0.008, "npc"),
                              type = "open", ends = "last")
                )

p5 <- p4 +
scale_color_manual(name=NULL,
                   values = c("red","black"))

p6 <- p5+
labs(x="Cluster",y="average logFC")+
geom_text(data=dfcol,
          aes(x=x,y=y,label=label),
          size =6,
          color ="white")
p7 <- p6+
theme_minimal()+
theme(
      axis.title = element_text(size = 13,
                                color = "black",
                                face = "bold"),
      axis.line.y = element_line(color = "black",
                                 size = 1.2),
      axis.line.x = element_blank(),
      axis.text.x = element_blank(),
      panel.grid = element_blank(),
      legend.position = "top",
      legend.direction = "vertical",
      legend.justification = c(1,0),
      legend.text = element_text(size = 15)
      )

pdf(paste(prefix,'_multideg.pdf'),18,10)
print(p7)
dev.off()
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容