This report compares the original implementation of derfinder
available at alyssafrazee/derfinder, DESeq2
, edgeR-robust
and our implementation of derfinder
using the exonic segments described in evaluate.html.
This section has the code for running edgeR-robust
and DESeq2
on the simulation data set using the known exons as features.
This first code chunk loads the necessary data.
The following code performs the DESeq2 analysis. Code is based on edgeR_Robust supplementary code. The main change is that it has been modified for the multi-group scenario.
## user system elapsed
## 0.812 0.020 0.832
The following code performs the DESeq2 analysis. Code is based on edgeR_Robust supplementary code. The main change is that it has been modified for the multi-group scenario.
## user system elapsed
## 1.907 0.050 1.957
Just as in evaluate.html we can compare the results against the exonic segments. From that document:
Next we can evaluate the simulation by classifying the exonic segments as whether they should be DE or not. Then, we can find if the DERs overlap such segments.
The following code is a subset of evaluate.html and generates the exonic segments.
The original derfinder implementation does not support multi-group comparisons. So we performed all pair comparisons for the three groups. We can extract those that are differentially expressed (states 3 and 4) with a FDR adjusted p-value < 0.05.
Due to the simulation setup, only one of the three groups is differentially expressed at a time. One option is to compare the exonic segments versus the resulting DERs and ask if the exonic segments overlap at least one DER as shown below.
## Overlaps DER (sig) -- original, min 1
## DE status FALSE TRUE Sum
## FALSE 96 15 111
## TRUE 11 158 169
## Sum 107 173 280
The results from the new implementation are shown below (extracted from evaluate.html). The original implementation has 15 false positive (versus 0 in the new implemenation) and less false negatives (11 versus 30).
## Overlaps DER (sig FDR) -- new
## DE status FALSE TRUE Sum
## FALSE 111 0 111
## TRUE 30 139 169
## Sum 141 139 280
However, because of the simulation setup, with the original implementation we would actually expect at least two DERs to overlap each exonic segment that was set to be DE. When doing this comparison, we get 3 false positives and 28 false negatives versus 0 and 30 in the new implementation.
## Overlaps DER (sig) -- original, min 2
## DE status FALSE TRUE Sum
## FALSE 108 3 111
## TRUE 28 141 169
## Sum 136 144 280
## [1] FALSE
While the global numbers are similar, the agreement at the exonic segment level is not perfect between the original and new implementations as shown below.
## original -- min 2
## new FALSE TRUE Sum
## FALSE 129 12 141
## TRUE 7 132 139
## Sum 136 144 280
The following code was adapted from evaluate.html and explores the false negatives when requiring at least 2 DERs to overlap each exonic segment. As with the new implementation, the original implementation struggles in genes where one of the transcripts was set to be DE while the other wasn't.
## Explore false negative segments using sig DERs
seg.fn <- which(segs$DE & !countOverlaps(segs, ori.de.sig) > 1)
## Some segments are short
summary(width(segs[seg.fn]))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.0 69.0 155.5 191.5 223.2 853.0
## new:
##
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.0 73.5 119.0 242.7 241.0 1844.0
chosen[chosen$gene_id == '6523', ]
## tx_idx tx_n tx_i gene_id ucsckg_id fasta_i DE group1 group2 group3
## 175 400 2 1 6523 uc003amc.3 457 FALSE normal normal normal
## 176 400 2 2 6523 uc011alz.2 458 TRUE normal normal high
## width readspertx mean1 mean2 mean3 case
## 175 5061 2024 2024 2024 2024 oneDE
## 176 4779 1912 1912 1912 3824 oneDE
## 6 / 28 of the segmeents are from gene with id 6523
## new is 9 / 30 for the same gene
tail(sort(table(names(segs[seg.fn]))))
##
## 7494 10738 339669 3976 6948 6523
## 1 2 2 2 4 6
## Cases of the genes with at least one FN segment
table(tapply(subset(chosen, gene_id %in% names(seg.fn))$case, subset(chosen, gene_id %in% names(seg.fn))$gene_id, unique))
##
## bothDE oneDE singleDE
## 2 11 4
## new:
##
## bothDE oneDE singleDE
## 1 10 5
## Type of gene where the segments come from. Mostly oneDE genes
table(sapply(names(segs[seg.fn]), function(x) { unique(chosen$case[chosen$gene_id == x]) }))
##
## bothDE oneDE singleDE
## 2 22 4
## new:
##
## bothDE oneDE singleDE
## 1 24 5
Just as a verification step, the exonic segments used are disjoint as well as the exons used for the counts-based methods. Also, each exonic segment overlaps only one exon.
max(countOverlaps(segs)) - 1
## [1] 0
max(countOverlaps(exons)) - 1
## [1] 0
table(countOverlaps(segs, exons))
##
## 1
## 280
Next, we can compare the exonic segments versus the significant DE exons as determined by DESeq2
. Significance can be determined by regular p-values, FDR FDR adjusted p-values (BH method), and FWER adjusted p-values (Holm method). In all cases we use a cutoff of < 0.05.
## Regular p-values
count_comp(deseq, ptype = 'pvalue')
## Overlaps DE exon
## DE status FALSE TRUE Sum
## FALSE 101 10 111
## TRUE 6 163 169
## Sum 107 173 280
## FDR adjusted p-values by method BH
count_comp(deseq)
## Overlaps DE exon
## DE status FALSE TRUE Sum
## FALSE 104 7 111
## TRUE 7 162 169
## Sum 111 169 280
## FWER adjusted p-values by method Holm
count_comp(deseq, ptype = 'holm')
## Overlaps DE exon
## DE status FALSE TRUE Sum
## FALSE 110 1 111
## TRUE 10 159 169
## Sum 120 160 280
identical(count_comp(deseq, ptype = 'holm'), count_comp(deseq, ptype = 'bonferroni'))
## [1] TRUE
As expected the number of false positives is the highest with regular p-values and the lowest with FWER adjusted p-values. In all cases, there are fewer false negatives compared to derfinder
.
Similar results are shown below when using edgeR-robust
.
## Regular p-values
count_comp(edger, ptype = 'pvalue')
## Overlaps DE exon
## DE status FALSE TRUE Sum
## FALSE 92 19 111
## TRUE 6 163 169
## Sum 98 182 280
## FDR adjusted p-values by method BH
count_comp(edger)
## Overlaps DE exon
## DE status FALSE TRUE Sum
## FALSE 98 13 111
## TRUE 6 163 169
## Sum 104 176 280
## FWER adjusted p-values by method Holm
count_comp(edger, ptype = 'holm')
## Overlaps DE exon
## DE status FALSE TRUE Sum
## FALSE 110 1 111
## TRUE 8 161 169
## Sum 118 162 280
identical(count_comp(edger, ptype = 'holm'), count_comp(edger, ptype = 'bonferroni'))
## [1] TRUE
We can first compare the results by using the DERs as the query and the exons as the subject. The following output shows the comparison using all DERs and exploring the mismatched cases. Then its repeated using the DERs ≥ 20 bp and a minimum overlap of 20bp.
For the mismatched cases of non-significant DERs overlapping a significant exon, we check:
For the other mismatched case, we check:
## Overlaps sig DE exon
## Significant DER (FDR) FALSE TRUE Sum
## FALSE 15 301 316
## TRUE 0 153 153
## Sum 15 454 469
## $n_overlaps
##
## 1 2
## 293 8
##
## $width_der
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 1.000 2.000 5.236 6.000 37.000
##
## $ders_per_exon_table
##
## 1 2 3 4 5 6 7 9 10 11 15 36 76
## 14 11 8 2 4 5 2 2 1 2 1 1 1
## [1] "No such cases"
## Overlaps sig DE exon (min 20bp)
## Significant DER (FDR) FALSE TRUE Sum
## FALSE 1 15 16
## TRUE 0 153 153
## Sum 1 168 169
## $n_overlaps
##
## 1 2
## 14 1
##
## $width_der
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 20.00 22.50 25.00 26.27 30.00 37.00
##
## $ders_per_exon_table
##
## 1 6
## 10 1
## [1] "No such cases"
Most of the non-significant DERs that overlap a significant exon are shorter than 20bp with the longest being 37bp long. When restricting the analysis to 20bp or longer DERs, 6 the DERs overlap a single exon. It is an exon from a gene with two isoforms where only one of them was set to be DE. As can be seen in the figure below, the F-statistics curve oscillates and a lower cutoff could have resulted in significant DERs in this exon.
We can now repeat the comparison using the exons as the query and the DERs as the subject.
For the mismatched cases of non-significant exons overlapping a significant DER, we check:
For the other mismatched case, we check:
## Overlaps sig DER (FDR)
## Significant DE exon FALSE TRUE Sum
## FALSE 120 0 120
## TRUE 22 129 151
## Sum 142 129 271
## [1] "No such cases"
## $width_exon
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 60.0 105.0 123.5 551.0 219.0 4971.0
##
## $distance_nearest_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 0 0 338500 401300 2986000
##
## $distance_nearest_sig_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 240 7876 99000 448000 531800 3512000
## Overlaps sig DER (FDR, min 20bp)
## Significant DE exon FALSE TRUE Sum
## FALSE 119 0 119
## TRUE 22 129 151
## Sum 141 129 270
## [1] "No such cases"
## $width_exon
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 60.0 105.0 123.5 551.0 219.0 4971.0
##
## $distance_nearest_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 0 0 338500 401300 2986000
##
## $distance_nearest_sig_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 240 7876 99000 448000 531800 3512000
We can further explore the cases where significant DE exons did not overlap a significant DER and compare against the exonic segments.
## [1] 4
##
## FALSE TRUE
## 3 15
##
## oneDE singleDE
## 3 3
##
## oneDE singleDE
## 12 3
##
## noneDE singleNotDE
## 1 1
##
## noneDE singleNotDE
## 2 1
Out of the 22 cases in disagreement (min overlap 0 bp), 4 of them are due to overlapping exons from both strands. 15 of these exons are correctly detected by DESeq2
whereas 3 are not. The ones incorrectly identified by derfinder
to not be DE are mostly (12 / 15) from genes with two isoforms with only one of them DE.
Similar comparison using DERs as query and exons as subject with edgeR-robust
results.
## Overlaps sig DE exon
## Significant DER (FDR) FALSE TRUE Sum
## FALSE 13 303 316
## TRUE 0 153 153
## Sum 13 456 469
## $n_overlaps
##
## 1 2
## 295 8
##
## $width_der
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 1.000 2.000 5.228 6.000 37.000
##
## $ders_per_exon_table
##
## 1 2 3 4 5 6 7 9 10 11 15 36 76
## 14 12 8 2 4 5 2 2 1 2 1 1 1
## [1] "No such cases"
## Overlaps sig DE exon (min 20bp)
## Significant DER (FDR) FALSE TRUE Sum
## FALSE 1 15 16
## TRUE 0 153 153
## Sum 1 168 169
## $n_overlaps
##
## 1 2
## 14 1
##
## $width_der
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 20.00 22.50 25.00 26.27 30.00 37.00
##
## $ders_per_exon_table
##
## 1 6
## 10 1
## [1] "No such cases"
The results are fairly similar to those from using DESeq2
.
Similar comparison using exons as query and DERs as subject with edgeR-robust
results.
## Overlaps sig DER (FDR)
## Significant DE exon FALSE TRUE Sum
## FALSE 114 0 114
## TRUE 28 129 157
## Sum 142 129 271
## [1] "No such cases"
## $width_exon
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 13.0 100.8 123.5 465.3 222.2 4971.0
##
## $distance_nearest_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 0 873 267300 9045 2986000
##
## $distance_nearest_sig_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 240 8392 95680 375600 509100 3512000
## Overlaps sig DER (FDR, min 20bp)
## Significant DE exon FALSE TRUE Sum
## FALSE 114 0 114
## TRUE 27 129 156
## Sum 141 129 270
## [1] "No such cases"
## $width_exon
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 60.0 105.0 128.0 482.1 224.5 4971.0
##
## $distance_nearest_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 0 809 277100 9577 2986000
##
## $distance_nearest_sig_sum
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 240 8914 95990 389400 515900 3512000
As before, we can further explore the mismatched cases where edgeR-robust
finds DE signal but derfinder
does not.
## [1] 5
##
## FALSE TRUE
## 7 16
##
## oneDE singleDE
## 4 3
##
## oneDE singleDE
## 13 3
##
## noneDE singleNotDE
## 3 1
##
## noneDE singleNotDE
## 6 1
The results are fairly similar to those from using DESeq2
. As shown below, they agree on all but 6 of the exons analyzed. In particular, the longest false positive exon by DESeq2
is also a FP with edgeR-robust
.
## edgeR vs DESeq2
addmargins(table('edgeR-robust' = edger$sig, 'DESeq2' = deseq$sig))
## DESeq2
## edgeR-robust FALSE TRUE Sum
## FALSE 114 0 114
## TRUE 6 151 157
## Sum 120 151 271
## Find FP errors
err_edger <- segs[intersect(subjectHits(findOverlaps(edger[j.simple], segs )), which(!mcols(segs)$DE))]
## Does it overlap FP from DESeq2? Yes
countOverlaps(err_deseq2, err_edger) == 1
## 10291
## TRUE
The following is a coverage plot of the longest exon where all methods agree that its differentially expressed.
## [1] 5069
## [1] 4999 6 2 1
## [1] TRUE FALSE FALSE FALSE
## gene_id DE case
## 38 27439 TRUE bothDE
## pdf
## 2
The following is a coverage plot of the longest exon where all methods agree that its not differentially expressed. For derfinder
, we are requiring DERs to be at least 20 bp long.
## [1] 5789
## [1] 17 7 1 1
## [1] TRUE FALSE FALSE FALSE
## gene_id DE case
## 52 6942 FALSE noneDE
## pdf
## 2
Globally, the results between the original implementation and our implementation of derfinder
are very similar, with both resulting in the same empirical power and absence of false positives. Both struggle in the scenario where one of the two isoforms of a gene was set to be differentially expressed.
When adjusting p-values to control the FDR, both DESeq2
and edgeR-robust
result in higher empirical power than derfinder
: 95.86 and 96.45 respectively versus 82.25. However, both DESeq2
and edgeR-robust
have non-zero false positive rates: 6.31 and 11.71 respectively. Their false discovery rate is: 4.14 and 7.39 respectively. Note that the number of false positives is reduced to 1 in both cases when controlling the FWER.
We knew from evaluate.html that derfinder
struggled in the scenario where a two transcript gene had only one of them set to be differentially expressed. DESeq2
and edgeR-robust
are able to correctly identify such exons as differentially expressed in most cases, but they also introduce some occasional false positives whose coverage plots do not reveal apparent differences between the groups.
## [1] "2015-04-06 21:38:54 EDT"
## user system elapsed
## 106.257 2.013 118.414
## setting value
## version R Under development (unstable) (2014-11-01 r66923)
## system x86_64, darwin10.8.0
## ui X11
## language (EN)
## collate en_US.UTF-8
## tz America/New_York
## package * version date source
## acepack 1.3.3.3 2013-05-03 CRAN (R 3.2.0)
## annotate 1.45.4 2015-03-21 Bioconductor
## AnnotationDbi * 1.29.21 2015-04-03 Bioconductor
## Biobase * 2.27.3 2015-03-27 Bioconductor
## BiocGenerics * 0.13.11 2015-04-03 Bioconductor
## BiocParallel 1.1.21 2015-03-24 Bioconductor
## biomaRt 2.23.5 2014-11-22 Bioconductor
## Biostrings 2.35.12 2015-03-26 Bioconductor
## biovizBase 1.15.3 2015-03-30 Bioconductor
## bitops 1.0.6 2013-08-17 CRAN (R 3.2.0)
## BSgenome 1.35.20 2015-03-27 Bioconductor
## bumphunter 1.7.6 2015-03-13 Github (lcolladotor/bumphunter@37d10e7)
## cluster 2.0.1 2015-01-31 CRAN (R 3.2.0)
## codetools 0.2.11 2015-03-10 CRAN (R 3.2.0)
## colorout * 1.0.2 2014-11-03 local
## colorspace 1.2.6 2015-03-11 CRAN (R 3.2.0)
## DBI 0.3.1 2014-09-24 CRAN (R 3.2.0)
## derfinder * 1.1.18 2015-04-01 Bioconductor
## derfinderHelper * 1.1.6 2015-03-15 Bioconductor
## derfinderPlot * 1.1.6 2015-03-14 Github (lcolladotor/derfinderPlot@1319754)
## DESeq2 * 1.7.50 2015-04-04 Bioconductor
## devtools 1.6.1 2014-10-07 CRAN (R 3.2.0)
## dichromat 2.0.0 2013-01-24 CRAN (R 3.2.0)
## digest 0.6.8 2014-12-31 CRAN (R 3.2.0)
## doRNG 1.6 2014-03-07 CRAN (R 3.2.0)
## edgeR * 3.9.15 2015-04-03 Bioconductor
## evaluate 0.5.5 2014-04-29 CRAN (R 3.2.0)
## foreach 1.4.2 2014-04-11 CRAN (R 3.2.0)
## foreign 0.8.63 2015-02-20 CRAN (R 3.2.0)
## formatR 1.0 2014-08-25 CRAN (R 3.2.0)
## Formula 1.2.0 2015-01-20 CRAN (R 3.2.0)
## futile.logger 1.4 2015-03-21 CRAN (R 3.2.0)
## futile.options 1.0.0 2010-04-06 CRAN (R 3.2.0)
## genefilter 1.49.2 2014-10-21 Bioconductor
## geneplotter 1.45.0 2014-10-14 Bioconductor
## GenomeInfoDb * 1.3.16 2015-03-27 Bioconductor
## GenomicAlignments 1.3.33 2015-04-06 Bioconductor
## GenomicFeatures * 1.19.36 2015-03-30 Bioconductor
## GenomicFiles 1.3.15 2015-04-01 Bioconductor
## GenomicRanges * 1.19.52 2015-04-04 Bioconductor
## GGally 0.4.8 2014-08-26 CRAN (R 3.2.0)
## ggbio 1.15.3 2015-04-02 Bioconductor
## ggplot2 1.0.0 2014-05-21 CRAN (R 3.2.0)
## graph 1.45.3 2015-04-03 Bioconductor
## gridExtra 0.9.1 2012-08-09 CRAN (R 3.2.0)
## gtable 0.1.2 2012-12-05 CRAN (R 3.2.0)
## Hmisc 3.14.5 2014-09-12 CRAN (R 3.2.0)
## htmltools 0.2.6 2014-09-08 CRAN (R 3.2.0)
## IRanges * 2.1.43 2015-03-07 Bioconductor
## iterators 1.0.7 2014-04-11 CRAN (R 3.2.0)
## knitr 1.7 2014-10-13 CRAN (R 3.2.0)
## knitrBootstrap 1.0.0 2014-11-03 Github (jimhester/knitrBootstrap@76c41f0)
## lambda.r 1.1.7 2015-03-20 CRAN (R 3.2.0)
## lattice 0.20.31 2015-03-30 CRAN (R 3.2.0)
## latticeExtra 0.6.26 2013-08-15 CRAN (R 3.2.0)
## limma * 3.23.12 2015-04-05 Bioconductor
## locfit 1.5.9.1 2013-04-20 CRAN (R 3.2.0)
## markdown 0.7.4 2014-08-24 CRAN (R 3.2.0)
## MASS 7.3.40 2015-03-21 CRAN (R 3.2.0)
## Matrix 1.2.0 2015-04-04 CRAN (R 3.2.0)
## matrixStats 0.14.0 2015-02-14 CRAN (R 3.2.0)
## mime 0.3 2015-03-29 CRAN (R 3.2.0)
## munsell 0.4.2 2013-07-11 CRAN (R 3.2.0)
## nnet 7.3.9 2015-02-11 CRAN (R 3.2.0)
## OrganismDbi 1.9.15 2015-03-30 Bioconductor
## pkgmaker 0.22 2014-05-14 CRAN (R 3.2.0)
## plyr 1.8.1 2014-02-26 CRAN (R 3.2.0)
## proto 0.3.10 2012-12-22 CRAN (R 3.2.0)
## qvalue * 1.99.1 2015-04-04 Bioconductor
## RBGL 1.43.0 2014-10-14 Bioconductor
## RColorBrewer 1.1.2 2014-12-07 CRAN (R 3.2.0)
## Rcpp * 0.11.5 2015-03-06 CRAN (R 3.2.0)
## RcppArmadillo * 0.4.650.1.1 2015-02-26 CRAN (R 3.2.0)
## RCurl 1.95.4.5 2014-12-28 CRAN (R 3.2.0)
## registry 0.2 2012-01-24 CRAN (R 3.2.0)
## reshape 0.8.5 2014-04-23 CRAN (R 3.2.0)
## reshape2 1.4.1 2014-12-06 CRAN (R 3.2.0)
## rmarkdown 0.3.3 2014-09-17 CRAN (R 3.2.0)
## rngtools 1.2.4 2014-03-06 CRAN (R 3.2.0)
## rpart 4.1.9 2015-02-24 CRAN (R 3.2.0)
## Rsamtools 1.19.49 2015-03-27 Bioconductor
## RSQLite 1.0.0 2014-10-25 CRAN (R 3.2.0)
## rstudioapi 0.2 2014-12-31 CRAN (R 3.2.0)
## rtracklayer 1.27.11 2015-04-01 Bioconductor
## S4Vectors * 0.5.22 2015-03-06 Bioconductor
## scales 0.2.4 2014-04-22 CRAN (R 3.2.0)
## stringr 0.6.2 2012-12-06 CRAN (R 3.2.0)
## survival 2.38.1 2015-02-24 CRAN (R 3.2.0)
## TxDb.Hsapiens.UCSC.hg19.knownGene * 3.0.0 2014-09-26 Bioconductor
## VariantAnnotation 1.13.46 2015-03-26 Bioconductor
## XML 3.98.1.1 2013-06-20 CRAN (R 3.2.0)
## xtable 1.7.4 2014-09-12 CRAN (R 3.2.0)
## XVector * 0.7.4 2015-02-08 Bioconductor
## yaml 2.1.13 2014-06-12 CRAN (R 3.2.0)
## zlibbioc 1.13.3 2015-03-23 Bioconductor