GSE83521/GSE89143去除批次效应

老大在群里出的题,说感觉这个热图很诡异,然后中间我自己没有用boxplot查看数据的表达量,对于数据不能有正确的认识,导致一开始的deg的logFC都没有达到正负1的,最重要的是:

1.是因为我知道什么情况下用log函数,然后我还在这里面错误的用了log函数;

2.不能用[1:4,1:4]查看数据集机构;

3.normalizeBetweenArraysremoveBatchEffect函数的用处。

老大帮助修改了代码,关于normalizeBetweenArraysremoveBatchEffectboxplot的,结果才清晰明了。

原文图片

image-20191211120910895

下载数据+准备数据

rm(list = ls())
options(stringsAsFactors = F)

library(GEOquery)
eSet1 <- getGEO("GSE83521",
                destdir = '.',
                getGPL = F)
#(1)提取表达矩阵exp
exp1 <- exprs(eSet1[[1]])
exp1[1:4,1:4]
dim(exp1)
# 一定要看boxplot
boxplot(exp1,las=2)
pd1 <- pData(eSet1[[1]])
#(3)提取芯片平台编号
gpl1 <- eSet1[[1]]@annotation
save(pd1,exp1,gpl1,file = "step1-1output.Rdata")
load("step1-1output.Rdata")
exp1的boxplot图
eSet2 <- getGEO("GSE89143",
                destdir = '.',
                getGPL = F)
#(1)提取表达矩阵exp
exp2 <- exprs(eSet2[[1]])
exp2[1:4,1:4]
dim(exp2)
boxplot(exp2,las=2)
image-20191211111523660

从上面的箱线图结果可以看到,数值的表达量并不在同一条水平线上,并且有成败上千,也有零,很明显是没有经过log的。这是需要把数据log后再用boxplot来看数据的分布,用boxplot来看数据的分布非常重要。不能仅仅用[1:4,1:4]来查看,因为[1:4,1:4]并不能看到整体的数据情况。关于为什么要log,是因为做差异分析的limma包要求表达矩阵中的数据是经过log的。可以参考老大的这篇:关于limma包差异分析结果的logFC解释

exp2 = log2(exp2+1)
boxplot(exp2,las=2)
image-20191211111614821

接下来这个函数厉害了,从上面的图中可以看到有一个样本的中位数和其他样本明显不在一条水平显示,这个normalizeBetweenArrays函数,可以把他拉回正常水平,normalizeBetweenArrays只能是在同一个数据集里面使用

library(limma)
exp2=normalizeBetweenArrays(exp2)
boxplot(exp2,las=2)
exp2的boxplot图

从上面的箱线图可以看到,exp2的数据的分布基本在一条水平线上。

接下来将exp2的数据保存

#(2)提取临床信息
pd2 <- pData(eSet2[[1]])
#(3)提取芯片平台编号
gpl2 <- eSet2[[1]]@annotation

#这些代码是什么鬼东西,我给你注释了。

index <- sort.int(pd2$characteristics_ch1,index.return = T)
class(index)
pd2 <- pd2[index$ix,]
exp2 <- exp2[,match(rownames(pd2),colnames(exp2))]

save(pd2,exp2,gpl2,file = "step1-2output.Rdata")
load("step1-2output.Rdata")

探针注释

## 是同一个平台,非常棒
gpl2
gpl1
if(T){
  library(GEOquery)
  gpl<- getGEO('GPL19978', destdir=".")
  dim(gpl)
  colnames(Table(gpl)) #查一下列明
  head(Table(gpl)[,c(1,2)])
  ids=Table(gpl)[,c(1,2)]
  ids <- ids[-c(1:2),]
  ids <- ids[-c(1:13),]
  save(ids,file='ids.Rdata')
}

看一下获得的探针和circ_RNA的对应关系

image-20191211182919882

差异分析-去除批次效应

x1 <- exp1[rownames(exp1) %in% ids$ID,]
x2 <- exp2[rownames(exp2) %in% ids$ID,]
boxplot(x1,las=2)
boxplot(x2,las=2)
cg=intersect(rownames(x1),rownames(x2))
x_merge=cbind(x1[cg,],x2[cg,])
  • 又有大招了,得到的这个merge后的表达矩阵x_merge,一定一定要用boxplot看一下,因为我们是将两个数据集通过共同的探针合并了,因为是来自两个数据,所以第一次在实际案例中接触到了这个高大上的名次-去除批次效应
  • 那么就boxplot来看看!
boxplot(x_merge)
image-20191211112227070

上面这张图,就是非常明显的看到了,由于后面的三个样本就是来自另一个数据集的。从前面的boxplot(exp2)也可以看到他的表达量在8以上。

pd1$title
pd2$characteristics_ch1
group_list <- c(rep('tumor',6),rep('normal',6),rep(c('tumor', 'normal'),each=3))
gse <- c(rep('GSE83527',12),rep('GSE89143',6))
table(group_list,gse)
dat <- x_merge
library(sva)
library(limma)
## 使用 limma 的 removeBatchEffect 函数
dat[1:4,1:4]
batch <- c(rep('GSE83521',12),rep('GSE89143',6))
design=model.matrix(~group_list)
ex_b_limma <- removeBatchEffect(dat,
                                batch = batch,
                                design = design)
dim(ex_b_limma)
  • 这个时候一定要看 boxplot , 不然就白学的了!!!!!
boxplot(ex_b_limma)
ex_b_limma
  • 从上面的图可以看到了,去除了批次效应后,数据的表达水平。

  • 接下来就做差异分析

{
  library(limma)
  fit=lmFit(ex_b_limma,design)
  fit=eBayes(fit)
  options(digits = 4)
  topTable(fit,coef=2,adjust='BH')
  deg=topTable(fit,coef=2,adjust='BH',number = Inf)
}

得到的deg如下图

image-20191211184520414

👆两张图主要是为了看logFC的值,我第一次把两个数据全部log并且没有进行一个normalizeBetweenArrays来去除样本间的批次差异,而没有一个logFC值是在>1和<-1的。

火山图

if(T){
  nrDEG=deg
  head(nrDEG)
  attach(nrDEG)
  plot(logFC,-log10(P.Value))
  library(ggpubr)
  df=nrDEG
  df$v= -log10(P.Value) #df新增加一列'v',值为-log10(P.Value)
  ggscatter(df, x = "logFC", y = "v",size=0.5)

  df$g=ifelse(df$P.Value>0.05,'stable', #if 判断:如果这一基因的P.Value>0.01,则为stable基因
              ifelse( df$logFC >1,'up', #接上句else 否则:接下来开始判断那些P.Value<0.01的基因,再if 判断:如果logFC >1.5,则为up(上调)基因
                      ifelse( df$logFC < -1,'down','stable') )#接上句else 否则:接下来开始判断那些logFC <1.5 的基因,再if 判断:如果logFC <1.5,则为down(下调)基因,否则为stable基因
  )
  table(df$g)
  df$name=rownames(df)
  head(df)
  ggscatter(df, x = "logFC", y = "v",size=0.5,color = 'g')
  ggscatter(df, x = "logFC", y = "v", color = "g",size = 0.5,
            label = "name", repel = T,
            #label.select = rownames(df)[df$g != 'stable'] ,
            label.select = head(rownames(deg)), #挑选一些基因在图中显示出来
            palette = c("#00AFBB", "#E7B800", "#FC4E07") )
  ggsave('volcano.png')

}

image-20191211180554248

热图

  • 在画特图前,还有一小问题,那么就是这个探针的问题,我们可以看到原文的热图上的基因是hsa-circ-0034398,而我们id转换后的表达矩阵的基因名是,如下图标记所示
image-20191211185647841

学习群里的小伙伴将一个Alias的对应表格分享到群里,把它读进R里进行进一步的转换,文件是ID.txt

if(T){
  up <- df[df$g=='up',]
  down <- df[df$g =='down',]
  x <- rbind(up,down)
  x$ID <- rownames(x)
  #上面是为了提取出差异基因的子集
  y <- merge(x,ids,by='ID') #merge函数可以根据两列共有的内容进行合并,合并后含有共有的行名
  ex_b_limma2 <- ex_b_limma[match(y$ID,rownames(ex_b_limma)),]
  rownames(ex_b_limma2) <- y$circRNA
  #上面的函数写的不咋好,命名变量不好命名,需要得到结果后看一下
  z <- read.csv('ID.txt',sep = '\t')
  tmp1 <- z[z$circRNA %in% rownames(ex_b_limma2),]
  ex_b_limma3 <- ex_b_limma2[match(tmp1$circRNA,rownames(ex_b_limma2)),]

  
  rownames(ex_b_limma3) <- tmp1$Alias
  library(pheatmap)
  pheatmap(ex_b_limma3,show_colnames =T,show_rownames = T) 
  n=t(scale(t(ex_b_limma3)))
  n[n>2]=2
  n[n< -2]= -2
  n[1:4,1:4]
  pheatmap(n,show_colnames =F,show_rownames = F)
  ac=data.frame(SampleType=group_list,#这步就是可以实现两个分组了
                GeoDatabase=gse)
  rownames(ac)=colnames(n) #将ac的行名也就分组信息 给到n的列名,即热图中位于上方的分组信息,这步很重要
  pheatmap(n,show_colnames =T,
           show_rownames = T,
           cluster_cols = F,
           annotation_col=ac,
           fontsize = 8,
           filename = 'deg-heatmap.png') #列名注释信息为ac即分组信息
}
image-20191211180139253

重要的如下:

1.理解boxplot的重要性,来看数据集是否需要log,以便后面才能用limma包进行差异分析

2.normalizeBetweenArrays只能是在同一个数据集里面用来去除样本的差异,不同数据集需要用limma 的 removeBatchEffect函数去除批次效应。

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

推荐阅读更多精彩内容