内容

1介绍

在这个案例研究中,我们假设读者熟悉的材料SummarizedBenchmark:介绍装饰图案,在较小程度上的内容SummarizedBenchmark:类的细节装饰图案。这两个小插曲提供更高级别介绍包,如果可能,应该先读。

图书馆(“SummarizedBenchmark”)图书馆(“magrittr”)图书馆(“limma”)图书馆(“磨边机”)图书馆(“DESeq2”)图书馆(“tximport”)

我们使用一个模拟数据集(Soneson和罗宾逊2016年)为了演示如何SummarizedBenchmark包可用于基准差异表达分析的方法。也就是说,我们比较的方法实现DESeq2,刨边机,limma包。模拟数据集包含6个样品的三个复制的两个条件。对于每一个样本,转录水平表达提供成绩单每百万(TPM)值15677成绩单从人类染色体1(运用GRCh37.71)。更完整的描述数据,包括代码的数据生成ws,可用的补充材料(Soneson和罗宾逊2016年)在这里。我们提供预先计算的对象包含这些统计数据和地面真理。细节都包含在生成的对象附录最后的装饰图案。

数据(“soneson2016”)(txi美元计数)
# # # # A1 A2 A3 B1 B2 ENST00000367770 1.670571 0.8064829 5.472561 558.834722 458.8887676 662.352695 5.299743 20.73813 58.700418 - 32.89297 # # ENST00000367771 # # ENST00000367772 155.881534 110.6033685 183.417201 11.809207 16.4752934 10.426669 20.392491 1.26733 0.000000 - 0.00000 # # ENST00000423670 # # ENST00000470238 96.489863 34.2755231 32.489730 12.442872 13.4797855 4.781290 1.152118 20.50770 785.514128 - 614.71261 # # ENST00000286031 # # # # B3 ENST00000367770 16.648100 # # ENST00000367771 14.862318 # # ENST00000367772 0.000000 7.546371 # # # # ENST00000423670 ENST00000470238 815.123229 # # ENST00000286031 5.760588
(truthdat)
# # #一个宠物猫:6×13 # #记录状态logFC_cat logFC avetpm长度eff_length tpm1 tpm2 # # <空空的> < int > <空空的> <双> <双> < int > <双> <双> <双> # # 1 ENST00000367770 1 [3.38, 3…4.17 0.225 2916 2771。0.0237 - 0.427 # # 2 ENST00000367771 1 [3.38, 3…5.25 3.20 2921 2776。6.23 - 0.164 # # 3 ENST00000367772 1正正0.817 3477 3332。1.63 0 # # 4 ENST00000423670 1 [0.00, 0.322 - 0.203…2077 1932。0.181 - 0.226 # # 5 ENST00000470238 1 [3.38, 3…4.07 4.08 1538 1393。0.460 - 7.71 # # 6 ENST00000286031 0 [0.00, 0.154…0 4355 4210。0.154 - 0.154 # # #ℹ4个变量:isopct1 <双>,isopct2 <双>、<科>基因,# # # avetpm_cat <空空的>

2基准的建立和执行

我们开始通过创建我们的基准测试过程BenchDesign对象的数据集。BenchDesign可以初始化data.frame(如介绍装饰图案),或更普遍的是,一个对象列表,或可选地,没有任何数据。在这个案例研究中,因为微分表达式需要的不仅仅是表达的方法,如实验设计,我们构建的数据集作为一个列表包含每一个输入为一个命名的入口。

按比例缩小的TPM值圆之前通过微分表达式的方法。

mycounts < -(txi美元计数)

在这里,我们只使用每个样本的条件来定义实验设计。设计矩阵存储为一个data.frame,mycoldat

mycoldat < -data.frame(条件=因素(代表(c(1,2),每一个=3)))rownames(mycoldat) < -colnames(mycounts)

基准实验的数据对象现在由计数和设计矩阵,以及一些地面实况信息(“状态”:真正的微分表达式之间是否存在条件下,和“利物浦”:预期log-fold变化之间的条件)。

mydat < -列表(coldat =mycoldat,cntdat =mycounts,状态=truthdat美元的地位,利物浦=truthdat美元logFC)

BenchDesign构造数据是唯一的输入。

bd < -BenchDesign(data =mydat)

为简单起见,我们只专注于比较每种方法所返回的假定值后测试两个条件之间的微分表达式。然而,在这个描述的后面,我们也展示了多个指标(假定值和log-fold变化)可以在一个比较BenchDesign对象。

因为每个方法需要运行多个步骤,我们为每个方法编写两个包装器函数,函数首先返回主分析结果,和第二个函数从结果中提取pvalues。

deseq2_run < -函数(colData countData设计、对比){dds < -DESeqDataSetFromMatrix(countDatacolData =colData,设计=设计)dds < -DESeq(dds)结果(dds,对比=对比)}deseq2_pv < -函数(x) {x美元pvalue}edgeR_run < -函数(countData、组设计){y < -DGEList(countData组=集团)y < -calcNormFactors(y)des < -model.matrix(设计)y < -estimateDisp(y, des)符合< -glmFit(y, des)glmLRT(健康,系数=2)}edgeR_pv < -函数(x) {x美元美元PValue}voom_run < -函数(countData、组设计){y < -DGEList(countData组=集团)y < -calcNormFactors(y)des < -model.matrix(设计)y < -(y, des)易趣(lmFit(des), y)}voom_pv < -函数(x) {x美元p.value (,2]}

请注意,我们也可以简单地编写一个包装器函数为每个方法只返回假定值的向量,例如总和deseq2_run ()deseq2_pv ()成一个单一的函数。这里我们单独的函数分成两个包装的目的仅仅是为了清晰性和一致性与后来的例子在这个故事。没有分开包装成两个小功能优势。接下来,添加到每个方法BenchDesign使用调用addMethod (),相应的包装器函数函数。(审查的基本用法调用addMethod (),revistSummarizedBenchmark:介绍装饰图案)。我们使用管道符号密实度。

bd < -双相障碍% > %调用addMethod(标签=“deseq2”,func =deseq2_run,帖子=deseq2_pv,params =rlang::、动荡频仍的(countData =cntdat,colData =coldat,设计=~条件下,对比=c(“条件”,“2”,“1”)))% > %调用addMethod(标签=“磨边机”,func =edgeR_run,帖子=edgeR_pv,params =rlang::、动荡频仍的(countData =cntdat,组=coldat美元条件下,设计=~coldat美元条件))% > %调用addMethod(标签=“轰”,func =voom_run,帖子=voom_pv,params =rlang::、动荡频仍的(countData =cntdat,组=coldat美元条件下,设计=~coldat美元条件))

到目前为止,没有一个方法执行。的BenchDesign描述对象只是作为一个容器如何应该执行的方法。方法被应用到一个简单的调用buildBench ()。因为地面真理是已知的和可用的mydat美元地位,这是指定truthCols =

某人< -buildBench(双相障碍,truthCols =“状态”)

我们可以检查结果。

某人
# #类:SummarizedBenchmark # #暗淡:15677(1):3 # #元数据会话# #化验(1):# # rownames现状:零构成了rowData名称(1):# # # # colnames状态(3):deseq2刨边机轰# # colData名称(9):函数。pkg func.pkg。更小……参数。集团session.idx

3基准评价

通过运行上面的代码,结果三个微分表达式的方法(刨边机,limma轰,DESeq2将存储在一个SummarizedBenchmark容器。下一步是定义指标来评估这三种方法的性能。这可以通过使用函数addPerformanceMetric ()之前描述的介绍装饰图案。在这个包中有实现几个常用的“默认”指标评价方法。这个函数availableMetrics ()返回一个data.frame这些指标。

availableMetrics()
# # 1 # #功能描述拒绝拒绝的# # 2 TPR真阳性率# # 3 # # TNR真阴性率4罗斯福错误发现率(估计)# # 5 FNR假阴性率# # 6相关皮尔逊相关# # 7 sdad标准差的绝对差# # 8 # #汉明汉明距离9 LPnorm L_ {p}规范# # 10 adjustedRandIndex调整兰德指数# # 1 # # requiresTruth假# # 2真# # 3真正的# # 4真正的# # 5真# # 6真正的# # 7真# # 8真# # 9真# # 10真的

预定义的标准拒绝,TPR,TNR,罗斯福FNR可以添加到化验吗H使用下面的代码的对象。

某人< -addPerformanceMetric(某人,evalMetric =c(“拒绝”,“TPR”,“TNR”,“罗斯福”,“FNR”),分析=“状态”)的名字(performanceMetrics(某人)[[“状态”]])
# #[1]“拒绝”“TPR”“TNR”“罗斯福”“FNR”

在定义所需的性能指标函数estimatePerformanceMetrics ()将计算这些指标的三种方法。

estimatePerformanceMetrics(某人,α=c(0.01,0.05,0.1,0.2),整洁的=真正的)% > %dplyr:::选择(标签、价值、performanceMetricα)% > %尾巴()
# #标签值performanceMetricα55 # # deseq2 0.10949477 FNR 0.1 # # 56刨边机0.09381113 FNR 0.1 # # 57轰0.11381970 FNR 0.1 # # 58 deseq2 0.09181118 FNR 0.2 # # 59刨边机0.07986767 FNR 0.2 # # 60轰0.08741018 FNR 0.2

此外,功能plotMethodsOverlap ()plotROC ()有助于形象化的表现不同的方法,在这些方法输出q值。

plotMethodsOverlap ()是一个包装器函数吗沮丧()UpSetR方案,有助于可视化之间的重叠的不同的方法对于一个给定的alpha值。

plotMethodsOverlap(某人,分析=“状态”,α=0.1,秩序。通过=“频率”)

从上面的图中,很明显,有大量的记录,发现差异表达的所有三种方法。还有小的记录集,通过一个单一的方法或发现独特的子集的方法。另一个典型的方法比较不同方法的性能接受者操作特征(ROC)曲线。这个函数plotROC ()输入一个SummarizeBenchmark对象和绘制ROC曲线中包含的所有方法。

SummarizedBenchmark::plotROC(某人,分析=“状态”)

4存储多个输出

上述案例研究已经认为我们感兴趣的一个数值向量为每个方法,即假定值的向量。这些假定值存储为唯一分析SummarizedBenchmark返回的对象buildBench ()。然而,在许多情况下,有多个值比较感兴趣的方法。例如,看估计log-fold变化除了时可能会假定值的比较方法的微分表达式。

BenchDesign框架支持多个化验的帖子=参数的调用addMethod ()调用。零个或指定一个函数的时候出现帖子=所有方法,在上面的例子中,结果被存储为一个分析。然而,如果帖子=传递一个命名列表功能,独立的分析将创建使用每个列表的名称和功能。自分析名字取自帖子=,列表中的所有条目必须命名。此外,由于在使用分析方法名称匹配的结果,如果一个方法是错过帖子=功能对于一个给定的试验名称,相应的列分析将被设置为NA

跟踪这两个假定值为每个方法和log-fold变化值,我们写一套新的包装器函数来提取log-fold变化为每个方法,类似于包装器函数中提取假定值的早些时候写的。与上面的例子,我们只希望每个方法的假定值,我们不能简单的编写一个包装器函数运行方法和提取结果。相反的,单独的func =帖子=规范是必要的。

deseq2_lfc < -函数(x) {x美元log2FoldChange}edgeR_lfc < -函数(x) {x美元美元logFC}voom_lfc < -函数(x) {x美元系数(2]}

主要的包装器函数和一个访问列表传递给函数func =帖子=分别。

bd < -BenchDesign(data =mydat)% > %调用addMethod(标签=“deseq2”,func =deseq2_run,帖子=列表(pv =deseq2_pv,利物浦=deseq2_lfc),params =rlang::、动荡频仍的(countData =cntdat,colData =coldat,设计=~条件下,对比=c(“条件”,“2”,“1”)))% > %调用addMethod(标签=“磨边机”,func =edgeR_run,帖子=列表(pv =edgeR_pv,利物浦=edgeR_lfc),params =rlang::、动荡频仍的(countData =cntdat,组=coldat美元条件下,设计=~coldat美元条件))% > %调用addMethod(标签=“轰”,func =voom_run,帖子=列表(pv =voom_pv,利物浦=voom_lfc),params =rlang::、动荡频仍的(countData =cntdat,组=coldat美元条件下,设计=~coldat美元条件))

BenchDesign评估使用buildBench (),由此产生的SummarizedBenchmark将生成的两个分析:“光伏”“利物浦”。和之前一样,可以使用指定的“真正的事实”truthCols =参数。当使用多个化验,truthCols =预计一个名为向量assay-name =“列名”对。

某人< -buildBench(bd =双相障碍,truthCols =c(pv =“状态”,利物浦=“利物浦”))某人
# #类:SummarizedBenchmark # #暗淡:15677(1):3 # #元数据会话# #化验(2):pv利物浦# # rownames:零构成了rowData名字# # (2):pv利物浦# # colnames (3): deseq2刨边机轰# # colData名称(9):函数。pkg func.pkg。更小……参数。集团session.idx

我们可以验证两个化验包含预期值。

(分析(某人,“光伏”))
# # # # deseq2刨边机轰[1]2.875541 e-04 2.074073 e-04 6.103023 e 03 # # [2] 2.799371 e-23 2.121422 e-16 1.239445 e-04 # # [3] 8.450676 e-14 3.109331 e-18 5.221157 e-06 # # [4] 6.930834 e-01 6.621236 e-01 3.357040 e-01 # # [5] 2.479616 e-11 2.468951 e-09 3.978989 e-04 # # [6] 9.057130 e-01 8.947438 e-01 e-01 5.199404
(分析(某人,“利物浦”))
# # deseq2刨边机轰# #(1)3.7329019 3.6767779 3.5232524 # #(2)-5.3905346 -5.3773940 -5.5543949 # #(3)-9.7125453 -10.2467488 -8.2533275 # #(4)-0.4706410 -0.4547095 -1.0510456 # #(5)3.7048724 3.7024426 3.9084940 # #(6日)-0.1554938 -0.1504299 -0.7607029

存储在每个试验的结果SummarizedBenchmark对象可以以同样的方式进行分析。

5回收一个BenchDesign

在早期,我们提到BenchDesign没有任何数据可以被初始化。在这里,我们描述为什么以及如何运行支持buildBench ()在一个BenchDesign不包含一个数据集。

当基准测试几种方法,它通常被认为是良好的实践应用方法不仅仅是一个数据集。SummarizedBenchmark框架下,这自然意味着回收同一组中定义的一个方法BenchDesign跨多个数据集对象。首先,我们初始化一个BenchDesign没有任何方法或数据集。

bdnull < -BenchDesign()bdnull
# # BenchDesign - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # #基准数据:基准方法:零# # # # # #

和之前一样,可以添加到方法BenchDesign调用addMethod ()和基准实验运行使用buildBench ()

bdnull < -bdnull% > %调用addMethod(标签=“bonf”,func =p.adjust,params =rlang::、动荡频仍的(p =pval,方法=“bonferroni”))% > %调用addMethod(标签=“黑洞”,func =p.adjust,params =rlang::、动荡频仍的(p =pval,方法=“黑洞”))

buildBench ()方法接受一个可选的data =参数。当指定,这个数据集是用于运行实验,采取优先于中指定的数据集(或失踪)BenchDesign对象。

buildBench(bdnulldata =tdat)
# #类:SummarizedBenchmark # #暗淡:50 2 # #元数据(1):会话# #化验(1):默认# # rownames:零构成了rowData名称(1):# # # # colnames违约(2):bonf BH # # colData名称(6):函数。pkg func.pkg。更小……参数。方法session.idx

通过指定数据中buildBench ()一步,同样的基准比较,中定义的共同之处BenchDesign对象,可以跨多个数据集进行持续。虽然这种方法即使共同工作BenchDesign对象包含一个默认的数据集,它是建议BenchDesign没有创建数据,以避免错误如果设计是在数据集之间重用。

6下一个步骤

最重要的特征SummarizedBenchmark工作流中演示了这个故事。附加功能和主题,包括如何错误处理,迭代的基准测试,并行化可以发现在不同的小插曲。

7附录

在这里,我们描述数据如何使用数据从ArrayExpress可供下载。每个示例中提供了表达数据RSEM输出格式。相应信息背后的地面实况模拟数据也可用,包括记录状态微分表达式。

首先,我们下载并导入转录水平TPM值使用tximport 1.29.0包并将这些数据存储在一个对象调用txi

图书馆(tximport)图书馆(readr)d < -tempdir()download.file(url =paste0(“https://www.ebi.ac.uk/arrayexpress/files/”,“e - mtab - 4119 / e - mtab - 4119. - processed.3.zip”),destfile =file.path(d,“samples.zip”))解压缩(file.path(d,“samples.zip”),exdir =d)fl < -list.files(d,模式=“* _rsem.txt”,full.names =真正的)的名字(fl) < -gsub(“样本(. *)_rsem.txt”,\ \1”,basename(fl))txi < -tximport(fl,txIn =真正的,txOut =真正的,geneIdCol =“gene_id”,txIdCol =“transcript_id”,countsCol =“expected_count”,lengthCol =“effective_length”,abundanceCol =“TPM”,countsFromAbundance =“scaledTPM”,进口国=函数(x) {readr::read_tsv(x)})

接下来,我们获得和负载的地面实况信息可以用于评估微分表达式的结果分析和保持宠物猫被称为truthdat

download.file(url =paste0(“https://www.ebi.ac.uk/arrayexpress/files/”,“e - mtab - 4119 / e - mtab - 4119. - processed.2.zip”),destfile =file.path(d,“truth.zip”))解压缩(file.path(d,“truth.zip”),exdir =d)truthdat < -read_tsv(file.path(d,“truth_transcript.txt”))

我们保存tximport结果和真相宠物猫在这个包中使用。

保存(truthdat txi文件=“. . /数据/ soneson2016.rda”)

引用

Soneson,夏洛特,罗宾逊和马克D。2016。“iCOBRA:开放、可再生的、标准化的基准和生活方法。”自然方法13 (4):283 - 83。https://doi.org/10.1038/nmeth.3805