GEO2R的limma差异分析流程【芯片microarray数据】附limma+RNAseq

参考学习GEO提供的GEO2R在线差异分析工具使用的代码流程。笔记里的代码在理解每一步的基础上,部分做了修改。但大致思路不变,即使用limma包对芯片测序数据进行差异分析(暂未涉及可视化的代码)。

示例数据

  • GSE:GSE43760
  • Selected group design:
    (1)Disease:"GSM1070439","GSM1070441", "GSM1070443", "GSM1070445", "GSM1070447", "GSM1070449"
    (2)Normal:"GSM1070451", "GSM1070453", "GSM1070455", "GSM1070457", "GSM1070459", "GSM1070461"

分析流程Pipeline

Step 1 :下载表达矩阵等

library(GEOquery)
GSE=paste0("GSE","43760")
gset=getGEO(GSE, getGPL = F)
class(gset)
#"list"
length(gset)
#1
  • 如上有两个注意点
    (1)设置不下载GPL注释信息,因为此前以专门整理了该GPL平台的基因注释信息,节省时间。详见之前得到笔记https://www.jianshu.com/p/d89a25d43549
    (2)初步下载的GSE对象格式之所以是list,是因为同一个GSE的samples可能分别在不同平台(gpl)测序结果,对应list里的不同元素组成。一般来说都是一个GSE对应一个GPL,但遇到多平台情况,需要注意自己选择的样本测序结果是什么平台,再进行选择。
gset_sub=gset[[1]]
gset_sub
# ExpressionSet (storageMode: lockedEnvironment)
# assayData: 32968 features, 24 samples
# element names: exprs
# protocolData: none
# phenoData
# sampleNames: GSM1070439 GSM1070440 ... GSM1070462 (24 total)
# varLabels: title geo_accession ... treatment:ch1 (41 total)
# varMetadata: labelDescription
# featureData: none
# experimentData: use 'experimentData(object)'
# pubMedIds: 23771909
# Annotation: GPL6244

# Get GPL ID
gpl=unique(gset_sub@phenoData@data[,"platform_id"])
[1] "GPL6244"

#Get expression matrix
expr=gset_sub@assayData$exprs
#[1] 32968    24

#Get sample meta(optional)
meta=gset_sub@phenoData@data[,grep(":ch1",colnames(gset_sub@phenoData@data))]
#[1] "disease state:ch1" "gender:ch1"        "individual:ch1"
#[4] "time:ch1"          "tissue:ch1"        "treatment:ch1"

Step 2:表达矩阵与分组设计

  • 首先需要核对下,表达数据是否已经经过log转换;如果没有则log转换下。GEO2R通过下述代码实现自动检测。
qx <- as.numeric(quantile(expr, c(0., 0.25, 0.5, 0.75, 0.99, 1.0), na.rm=T))
LogC <- (qx[5] > 100) ||
  (qx[6]-qx[1] > 50 && qx[2] > 0)
if (LogC) { expr[which(expr <= 0)] <- NaN
    expr <- log2(expr) }
  • 然后根据选择的分组取表达矩阵的子集
GSM_case=c("GSM1070439","GSM1070441", "GSM1070443", "GSM1070445", "GSM1070447", "GSM1070449")
GSM_normal=c("GSM1070451", "GSM1070453", "GSM1070455", "GSM1070457", "GSM1070459", "GSM1070461")

index_case=which(colnames(expr) %in% GSM_case)
index_control=which(colnames(expr) %in% GSM_normal)

expr_sle=expr[,c(index_case,index_control)]
  • 分组设计
groups=factor(c(rep(1,length(index_case)),rep(0,length(index_control))),
                levels=c(0,1),labels = c("normal","disease"))

Step 3:limma包差异分析

library(limma)
#首先设置分组矩阵,指明所有sample的分组情况
design=model.matrix(~0+groups) 
colnames(design) <- levels(groups)
#      disease normal
# 1        0      1
# 2        0      1
# 3        0      1
# 4        0      1
# 5        0      1
# 6        0      1
# 7        1      0
# 8        1      0
# 9        1      0
# 10       1      0
# 11       1      0
# 12       1      0

#然后根据分组进行线性拟合
fit <- lmFit(expr_sle, design)

#需要进一步指明差异分析的比较为 disease组 VS normal组
cts <- paste("disease", "normal", sep="-") #注意顺序:前者比上后者
cont.matrix <- makeContrasts(contrasts=cts, levels=design) #比较矩阵,指明哪两组进行比较
fit2 <- contrasts.fit(fit, cont.matrix)

#最后得到差异分析结果
fit2 <- eBayes(fit2, 0.01)
tT <- topTable(fit2, adjust="fdr", sort.by="p",number=Inf)
head(tT)
#           logFC  AveExpr         t      P.Value    adj.P.Val        B
# 8107769 -0.8016667 9.627500 -6.764851 1.062535e-05 0.1905344 2.556737
# 7892531 -0.6966667 7.201667 -6.207964 2.611828e-05 0.1905344 1.959251
# 7894928 -0.7716667 6.700833 -6.123500 3.004739e-05 0.1905344 1.863787
# 7893992 -0.9983333 7.504167 -6.065703 3.309032e-05 0.1905344 1.797715
# 8012349 -1.3166667 8.798333 -5.915814 4.258809e-05 0.1905344 1.623514
# 8059996 -0.9233333 7.895000 -5.890448 4.445985e-05 0.1905344 1.593624

deg <- data.frame(Probe=rownames(tT),P.Value=tT[,"P.Value"],
                  logFC=tT[,"logFC"],FDR=tT[,"adj.P.Val"])

Step 4:结合GPL平台信息注释symbo基因名

gpl_anno=read.csv(paste0("/your path/to/GPL_array/",gpl,".csv"))
gpl_anno[,1]=as.character(gpl_anno[,1])
deg=dplyr::left_join(deg,gpl_anno[,-3],by=c("Probe"="ID"))
deg=na.omit(deg)
rownames(deg)=1:nrow(deg)
#    Probe      logFC    P.Value       FDR     Symbol
# 1 8107769 -0.8016667 -0.8016667 0.1905344    SLC12A2
# 2 8012349 -1.3166667 -1.3166667 0.1905344       PER1
# 3 8059996 -0.9233333 -0.9233333 0.1905344       PER2
# 4 7899018 -0.4683333 -0.4683333 0.1905344     TMEM57
# 5 7937696  0.7750000  0.7750000 0.2157829 KRTAP5-AS1
# 6 7897449 -0.4866667 -0.4866667 0.2164292      SPSB1

  • 以上是针对GEO2R里结合limma对芯片数据分析的方法;
  • 如果是RNAseq的counts数据,则需要结合edgeR包的voom()函数,总体思路不变(不需要考虑GPL的基因名注释问题了),相关代码如下。
  • 示例数据:GSE75852


#加载包
library(limma)
library(edgeR)
library(GEOquery)
library(data.table)
#下载数据
count_link="https://ftp.ncbi.nlm.nih.gov/geo/series/GSE75nnn/GSE75852/suppl/GSE75852_gene_count_frags.txt.gz"
# https://ftp.ncbi.nlm.nih.gov/geo/series/GSE112nnn/GSE112348/suppl/
counts=as.data.frame(fread(count_link))
colnames(counts)
counts[1:4,1:4]
#group分组
gset=getGEO("GSE75852",getGPL = F)
gsms=gset[[1]]@phenoData@data[,grep(":ch1",colnames(gset[[1]]@phenoData@data))]
index_case=which(gsms[,1]=="induced pluripotent stem cell" &
                            gsms[,2]=="Ataxia Telangiectasia")
index_control=which(gsms[,1]=="induced pluripotent stem cell" &
                            gsms[,2]=="Normal")

counts_sub=data.frame(counts[,c(index_case+1,index_control+1)],row.names=counts[,1])
groups=factor(c(rep(1,length(index_case)),rep(0,length(index_control))),
              levels=c(0,1),labels = c("normal","disease"))
design=model.matrix(~0+groups) 
colnames(design) <- levels(groups)
#limma+voom差异分析
v <- voom(counts_sub,design,normalize="quantile")
fit <- lmFit(v,design)
cts <- paste("disease", "normal", sep="-") 
cont.matrix <- makeContrasts(contrasts=cts, levels=design)
fit2 <- contrasts.fit(fit, cont.matrix)
fit2 <- eBayes(fit2, 0.01)
tT <- topTable(fit2, adjust="fdr", sort.by="p",number=Inf)
deg <- data.frame(Probe=rownames(tT),P.Value=tT[,"P.Value"],
                  logFC=tT[,"logFC"],FDR=tT[,"adj.P.Val"],AveExpr=tT[,"AveExpr"])
head(deg)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容