DESeq2分析转录组之数据导入
刘小泽写于19.4.20+4.25
前段时间事情有点多,但是我又回归啦!!!
来到大美横琴,感觉活力满满~舒心工作,开心生活!
来自于:https://www.bioconductor.org/packages/devel/bioc/vignettes/DESeq2/inst/doc/DESeq2.html#how-do-i-use-vst-or-rlog-data-for-differential-testing
这个教程还比较新,当前版本2019-4-12,基于DESeq2 的1.23.10版本,有兴趣可以自行探索英文说明书。我目前使用的版本是1.22.2另外还有一个 An RNA-seq workflow 教程,但是其中包含的内容有点复杂
前言
做转录组RNA-seq的一个重要目的就是找到差异基因,一般我们会从公司那里或者自己上游分析得到的原始表达矩阵再进行下游分析,其中count值就是每个样本中比对到每个基因的reads数。能做差异基因筛选这件事的包除了DESeq2还有edgeR, limma, DSS, EBSeq和 baySeq.
DESeq2是利用负二项分布广义线性模型( negative binomial generalized linear models),同时,还利用了离散型估计、logFoldChange
具体的模型含义可以搜索,但首先要明白的是负二项分布是一个离散分布,符合测序reads分布
快速了解
现有一个大体印象,假设现在有一个表达矩阵cts
,样本信息coldata
,其中的design
表示怎样设计样本的模型(这里表示既考虑样本条件condition
,又考虑了批次效应batch
,并且这两项都要是coldata
的因子型变量)
# 这里演示的就是普通的矩阵导入
dds <- DESeqDataSetFromMatrix(countData = cts,
colData = coldata,
design= ~ batch + condition)
dds <- DESeq(dds)
resultsNames(dds) # lists the coefficients
res <- results(dds, name="condition_trt_vs_untrt")
# or to shrink log fold changes association with condition:
res <- lfcShrink(dds, coef="condition_trt_vs_untrt", type="apeglm")
DESeq2可以和一些上游的定量软件兼容,比如:
- 如果用
Salmon
、Sailfish
、kallisto
得到表达矩阵,那么就可以用DESeqDataSetFromTximport
导入 - 如果有
htseq
得到的,就利用DESeqDataSetFromHTSeq
- 如果有
RangedSummarizedExperiment
得到的,利用DESeqDataSet
,
RangedSummarizedExperiment
输入数据要注意:
首先=》为什么用原始数据(没有标准化的数据)?
DESeq2规定:不论是RNA-seq还是其他高通量数据,都要用原始的整数型矩阵(matrix of integer values),比如i行xj列
的矩阵中取出来第i行,第j列,表示的就是:在sample j
中有多少reads比对到了gene i
上;RNA-seq这里的行表示的是基因,同样类比到另一种高通量数据,比如ChIP-seq,矩阵的行就可能表示 结合区域(binding regions)
官方解释不使用标准化数据原因如下:
The DESeq2 model internally corrects for library size, so transformed or normalized values such as counts scaled by library size should not be used as input.
就是为了利用自身算法校正文库差异
然后=》关于DESeqDataSet对象
DESeq2包会使用DESeqDataSet对象存储原始表达量以及中间的估算值,在代码中常常用dds
表示。这个对象可以看做是 SummarizedExperiment 包的RangedSummarizedExperiment对象扩展,那么其中的Ranged表示含义就是表达矩阵的每一行与基因组区间(基因的外显子)相联系,这样可以方便下游探索(比如:找到差异表达基因的ChIP-seq最临近的峰)
另外,这个对象必须有一个design表达式,用于估算数据分布以及后期log2FC值,形式一般是~ variable1 + variable2
,并且control一般在前,处理在后。
the
formula
expresses how the counts for each gene depend on the variables incolData
比如:用group list作为design表达式,那么group list的样子一般就是:
> group_list
[1] untrt trt untrt trt untrt trt untrt trt
Levels: trt untrt
有4种构建DESeqDataSet的方法,取决于上游得到counts矩阵的方法
利用tximport
支持Salmon、Sailfish、kallisto、RSEM的表达量数据,这些方法产生的数据特点如下:
- 校正了样本间基因长度的差异 (Trapnell et al. 2013)
- 不基于比对的方法节省内存与空间
- 避免将比对到多个基因同源区段的fragments丢掉,提高敏感度 (Robert and Watson 2015)
在进行上游Salmon分析时,这里推荐使用—gcBias
参数,可以进行RNAseq数据的系统误差校正(Love, Hogenesch, and Irizarry 2016; Patro et al. 2017),除非很明确数据中没有这种bias。这里为了测试选择了tximportData
包中的Salmon定量数据quant.sf
注意这里寻找文件的方法,这样不用自己去找路径,利用
system.file
和file.path
很方便。另外一般样本数据中会构建好了condition信息,但是这里为了演示,手动构建一下。
首先读入样本信息
library("tximport")
library("readr")
library("tximportData")
dir <- system.file("extdata", package="tximportData")
samples <- read.table(file.path(dir,"samples.txt"), header=TRUE)
# 构建condition
samples$condition <- factor(rep(c("A","B"),each=3))
rownames(samples) <- samples$run
samples[,c("pop","center","run","condition")]
## pop center run condition
## ERR188297 TSI UNIGE ERR188297 A
## ERR188088 TSI UNIGE ERR188088 A
## ERR188329 TSI UNIGE ERR188329 A
## ERR188288 TSI UNIGE ERR188288 B
## ERR188021 TSI UNIGE ERR188021 B
## ERR188356 TSI UNIGE ERR188356 B
然后准备表达量信息,需要表达矩阵文件以及转录本、基因关系文件
# 找到各个样本对应的表达文件,并更改列名为样本名
files <- file.path(dir,"salmon", samples$run, "quant.sf.gz")
names(files) <- samples$run
# 之后读入一个转录本对应基因的文件
tx2gene <- read_csv(file.path(dir, "tx2gene.gencode.v27.csv"))
head(tx2gene)
# A tibble: 6 x 2
TXNAME GENEID
<chr> <chr>
1 ENST00000456328.2 ENSG00000223972.5
2 ENST00000450305.2 ENSG00000223972.5
3 ENST00000473358.1 ENSG00000243485.5
4 ENST00000469289.1 ENSG00000243485.5
5 ENST00000607096.1 ENSG00000284332.1
6 ENST00000606857.1 ENSG00000268020.3
接着就是导入了
> txi <- tximport(files, type="salmon", tx2gene=tx2gene)
reading in files with read_tsv
1 2 3 4 5 6
summarizing abundance
summarizing counts
summarizing length
最后,利用txi
对象和样本信息构建DESeqDataSet
library("DESeq2")
ddsTxi <- DESeqDataSetFromTximport(txi,
colData = samples,
design = ~ condition)
# ddsTxi对象就可以继续进行下游分析了
利用count matrix
如果之前已经有了表达矩阵,那么就可以主要使用DESeqDataSetFromMatrix
函数。主要需要三个东西:原始表达矩阵(例如featureCounts产生的)、样本信息(就是表达矩阵的列名,要求是一个数据框)、design表达式
这里利用 pasilla 包的示例数据进行演示,其中表达矩阵是cts
,样本信息是coldata
library("pasilla")
pasCts <- system.file("extdata",
"pasilla_gene_counts.tsv",
package="pasilla", mustWork=TRUE)
pasAnno <- system.file("extdata",
"pasilla_sample_annotation.csv",
package="pasilla", mustWork=TRUE)
# 表达量
cts <- as.matrix(read.csv(pasCts,sep="\t",row.names="gene_id"))
# 样本
coldata <- read.csv(pasAnno, row.names=1)
coldata <- coldata[,c("condition","type")]
# 检查一下表达量矩阵是否和样本信息的顺序相同
> head(cts,2)
untreated1 untreated2 untreated3 untreated4 treated1 treated2
FBgn0000003 0 0 0 0 0 0
FBgn0000008 92 161 76 70 140 88
treated3
FBgn0000003 1
FBgn0000008 70
> coldata
condition type
treated1fb treated single-read
treated2fb treated paired-end
treated3fb treated paired-end
untreated1fb untreated single-read
untreated2fb untreated single-read
untreated3fb untreated paired-end
untreated4fb untreated paired-end
结果发现表达量和样本顺序是不同的,但事实上,必须保证表达矩阵的列名与样本信息的行名一致,DESeq2是不会智能区分的,否则后面运行就会报错;除了让它们的顺序保持一致以外,还要让coldata的行名中fb
字符去掉
# 先去掉coldata的行名中fb字符
> rownames(coldata) <- sub("fb", "", rownames(coldata))
> all(rownames(coldata) %in% colnames(cts))
[1] TRUE
# 然后判断现在表达矩阵与样本信息是否一致
> all(rownames(coldata) == colnames(cts))
[1] FALSE
# 重新按照coldata的行名排序即可
> cts <- cts[, rownames(coldata)]
> all(rownames(coldata) == colnames(cts))
[1] TRUE
接下来直接导入即可
library("DESeq2")
dds <- DESeqDataSetFromMatrix(countData = cts,
colData = coldata,
design = ~ condition)
> dds
class: DESeqDataSet
dim: 14599 7
metadata(1): version
assays(1): counts
rownames(14599): FBgn0000003 FBgn0000008 ... FBgn0261574 FBgn0261575
rowData names(0):
colnames(7): treated1 treated2 ... untreated3 untreated4
colData names(2): condition type
另外如果有额外的基因feature信息,也可以使用S4的DataFrame
函数添加到dds
的metadata
中
featureData <- data.frame(gene=rownames(cts))
mcols(dds) <- DataFrame(mcols(dds), featureData)
mcols(dds)
对于htseq-count
主要利用DESeqDataSetFromHTSeqCount
导入Htseq数据(虽然目前来讲featureCounts速度要比Htseq快得多,但是htseq依然许多人在用)
首先还是先指定数据位置
# 实际分析时可以这样
directory <- "/path/to/your/files/"
# 这里测试还是用pasilla包
directory <- system.file("extdata", package="pasilla",
mustWork=TRUE)
# 使用list.files()可以列出当前文件夹下有哪些文件
# 并找到文件名中包含有treated字符的
sampleFiles <- grep("treated",list.files(directory),value=TRUE)
# 直接在文件名基础上提取condition的信息,这样保证了表达量矩阵和样本的一一对应
sampleCondition <- sub("(.*treated).*","\\1",sampleFiles) #其中\\1代表括号中匹配到的内容
> sampleTable
sampleName fileName condition
1 treated1fb.txt treated1fb.txt treated
2 treated2fb.txt treated2fb.txt treated
3 treated3fb.txt treated3fb.txt treated
4 untreated1fb.txt untreated1fb.txt untreated
5 untreated2fb.txt untreated2fb.txt untreated
6 untreated3fb.txt untreated3fb.txt untreated
7 untreated4fb.txt untreated4fb.txt untreated
最后
library("DESeq2")
ddsHTSeq <- DESeqDataSetFromHTSeqCount(sampleTable = sampleTable,
directory = directory,
design= ~ condition)
> ddsHTSeq
class: DESeqDataSet
dim: 70463 7
metadata(1): version
assays(1): counts
rownames(70463): FBgn0000003:001 FBgn0000008:001 ... FBgn0261575:001
FBgn0261575:002
rowData names(0):
colnames(7): treated1fb.txt treated2fb.txt ... untreated3fb.txt
untreated4fb.txt
colData names(1): condition
利用SummarizedExperiment
library("airway")
data("airway")
se <- airway
library("DESeq2")
ddsSE <- DESeqDataSet(se, design = ~ cell + dex)
# design表达式:~ group + condition
> ddsSE
class: DESeqDataSet
dim: 64102 8
metadata(2): '' version
assays(1): counts
rownames(64102): ENSG00000000003 ENSG00000000005 ... LRG_98 LRG_99
rowData names(0):
colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
colData names(9): SampleName cell ... Sample BioSample
欢迎关注我们的公众号~_~
我们是两个农转生信的小硕,打造生信星球,想让它成为一个不拽术语、通俗易懂的生信知识平台。需要帮助或提出意见请后台留言或发送邮件到jieandze1314@gmail.com