Functions
rnorm(10) # sample 10 random normal deviates
## [1] -0.8064858 1.0638622 0.3445391 -0.6743962 0.5320705 0.8847153 0.2709375 0.8436201
## [9] 0.1594222 -0.4931706
rnorm(10)
the same as rnorm(n=10)
rnorm(n=10, mean=0, sd=1)
?rnorm
Vectors
c(TRUE, FALSE)
), integer (1:5
), numeric (rnorm(10)
), character (c("alpha", "beat")
), complexNA
), factors (factor(c("Female", "Male"))
), formulas (y ~ x
)x <- rnorm(1000)
y <- x + rnorm(1000)
plot(y ~ x)
Objects: classes and methods
data.frame()
, matrix()
lm()
df <- data.frame(Y = y, X = x)
fit <- lm(Y ~ X, df)
plot(Y ~ X, df)
abline(fit, col="red", lwd=2)
anova(fit)
## Analysis of Variance Table
##
## Response: Y
## Df Sum Sq Mean Sq F value Pr(>F)
## X 1 908.41 908.41 895.63 < 2.2e-16 ***
## Residuals 998 1012.24 1.01
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Packages
stats
, graphics
, Matrix
ggplot2
, dplyr
, ade
install.packages()
(or biocLite()
, below)library(ggplot2)
ggplot(df, aes(x=X, y=Y)) + geom_point() + geom_smooth(color="blue") +
geom_smooth(method="lm", color="red")
Help!
help.start()
?rnorm
class(fit)
; methods(plot)
; methods(class=class(fit))
?"plot<tab>...
Biological domains
Principles
Interoperability
DNAStringSet()
, rather than character vector.Reproducibility
Installation and use
biocLite("DESeq2")
; also works for CRAN & github packagesSix stages
Key packages: data access
Coordinated management: SummarizedExperiment
This is derived from: RNA-Seq workflow: gene-level exploratory analysis and differential expression, by Michael Love, Simon Anders, Wolfgang Huber; modified by Martin Morgan, October 2015.
We walk through an end-to-end RNA-Seq differential expression workflow, using DESeq2 along with other Bioconductor packages.
The complete work flow starts from the FASTQ files, but we will start after reads have been aligned to a reference genome and reads overlapping known genes have been counted.
Our main focus is on differential gene expression analysis with DESeq2. Other Bioconductor packages are important in statistical inference of differential expression at the gene level, including Rsubread, edgeR, limma, BaySeq, and others.
The data are from an RNA-Seq experiment of airway smooth muscle cells treated with dexamethasone, a synthetic glucocorticoid steroid with anti-inflammatory effects. Glucocorticoids are used, for example, in asthma patients to prevent or reduce inflammation of the airways.
In the experiment, four primary human airway smooth muscle cell lines were treated with 1 micromolar dexamethasone for 18 hours. For each of the four cell lines, we have a treated and an untreated sample. The reference for the experiment is:
Himes BE, Jiang X, Wagner P, Hu R, Wang Q, Klanderman B, Whitaker RM, Duan Q, Lasky-Su J, Nikolos C, Jester W, Johnson M, Panettieri R Jr, Tantisira KG, Weiss ST, Lu Q. “RNA-Seq Transcriptome Profiling Identifies CRISPLD2 as a Glucocorticoid Responsive Gene that Modulates Cytokine Function in Airway Smooth Muscle Cells.” PLoS One. 2014 Jun 13;9(6):e99625. PMID: 24926665. GEO: GSE52778.
Counts
summarizeOverlaps()
, etc.)SummarizedExperiment
library(airway)
data("airway")
se <- airway
Assay data
head(assay(se))
## SRR1039508 SRR1039509 SRR1039512 SRR1039513 SRR1039516 SRR1039517 SRR1039520
## ENSG00000000003 679 448 873 408 1138 1047 770
## ENSG00000000005 0 0 0 0 0 0 0
## ENSG00000000419 467 515 621 365 587 799 417
## ENSG00000000457 260 211 263 164 245 331 233
## ENSG00000000460 60 55 40 35 78 63 76
## ENSG00000000938 0 0 2 0 1 0 0
## SRR1039521
## ENSG00000000003 572
## ENSG00000000005 0
## ENSG00000000419 508
## ENSG00000000457 229
## ENSG00000000460 60
## ENSG00000000938 0
Experimental design
colData(se)
## DataFrame with 8 rows and 9 columns
## SampleName cell dex albut Run avgLength Experiment Sample
## <factor> <factor> <factor> <factor> <factor> <integer> <factor> <factor>
## SRR1039508 GSM1275862 N61311 untrt untrt SRR1039508 126 SRX384345 SRS508568
## SRR1039509 GSM1275863 N61311 trt untrt SRR1039509 126 SRX384346 SRS508567
## SRR1039512 GSM1275866 N052611 untrt untrt SRR1039512 126 SRX384349 SRS508571
## SRR1039513 GSM1275867 N052611 trt untrt SRR1039513 87 SRX384350 SRS508572
## SRR1039516 GSM1275870 N080611 untrt untrt SRR1039516 120 SRX384353 SRS508575
## SRR1039517 GSM1275871 N080611 trt untrt SRR1039517 126 SRX384354 SRS508576
## SRR1039520 GSM1275874 N061011 untrt untrt SRR1039520 101 SRX384357 SRS508579
## SRR1039521 GSM1275875 N061011 trt untrt SRR1039521 98 SRX384358 SRS508580
## BioSample
## <factor>
## SRR1039508 SAMN02422669
## SRR1039509 SAMN02422675
## SRR1039512 SAMN02422678
## SRR1039513 SAMN02422670
## SRR1039516 SAMN02422682
## SRR1039517 SAMN02422673
## SRR1039520 SAMN02422683
## SRR1039521 SAMN02422677
design = ~ cell + dex
se$dex <- relevel(se$dex, "untrt") # 'untrt' as reference level
cell
) plus treatment (dex
)Features (genes)
rowRanges(se)
## GRangesList object of length 64102:
## $ENSG00000000003
## GRanges object with 17 ranges and 2 metadata columns:
## seqnames ranges strand | exon_id exon_name
## <Rle> <IRanges> <Rle> | <integer> <character>
## [1] X [99883667, 99884983] - | 667145 ENSE00001459322
## [2] X [99885756, 99885863] - | 667146 ENSE00000868868
## [3] X [99887482, 99887565] - | 667147 ENSE00000401072
## [4] X [99887538, 99887565] - | 667148 ENSE00001849132
## [5] X [99888402, 99888536] - | 667149 ENSE00003554016
## ... ... ... ... ... ... ...
## [13] X [99890555, 99890743] - | 667156 ENSE00003512331
## [14] X [99891188, 99891686] - | 667158 ENSE00001886883
## [15] X [99891605, 99891803] - | 667159 ENSE00001855382
## [16] X [99891790, 99892101] - | 667160 ENSE00001863395
## [17] X [99894942, 99894988] - | 667161 ENSE00001828996
##
## ...
## <64101 more elements>
## -------
## seqinfo: 722 sequences (1 circular) from an unspecified genome
Create DESeqDataSet
object
library(DESeq2)
dds <- DESeqDataSet(se, design = ~ cell + dex)
Run the pipeline
dds <- DESeq(dds)
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
Summarize results
res <- results(dds)
head(res)
## log2 fold change (MAP): dex trt vs untrt
## Wald test p-value: dex trt vs untrt
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue padj
## <numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000000003 708.6021697 -0.37424998 0.09873107 -3.7906000 0.0001502838 0.001251416
## ENSG00000000005 0.0000000 NA NA NA NA NA
## ENSG00000000419 520.2979006 0.20215551 0.10929899 1.8495642 0.0643763851 0.192284345
## ENSG00000000457 237.1630368 0.03624826 0.13684258 0.2648902 0.7910940556 0.910776144
## ENSG00000000460 57.9326331 -0.08523371 0.24654402 -0.3457140 0.7295576905 0.878646940
## ENSG00000000938 0.3180984 -0.11555969 0.14630532 -0.7898530 0.4296136373 NA
mcols(res) # what does each column mean?
## DataFrame with 6 rows and 2 columns
## type description
## <character> <character>
## 1 intermediate mean of normalized counts for all samples
## 2 results log2 fold change (MAP): dex trt vs untrt
## 3 results standard error: dex trt vs untrt
## 4 results Wald statistic: dex trt vs untrt
## 5 results Wald test p-value: dex trt vs untrt
## 6 results BH adjusted p-values
head(res[order(res$padj),]) # 'top table' by p-adj
## log2 fold change (MAP): dex trt vs untrt
## Wald test p-value: dex trt vs untrt
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue padj
## <numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000152583 997.4398 4.316100 0.1724127 25.03354 2.637881e-138 4.755573e-134
## ENSG00000165995 495.0929 3.188698 0.1277441 24.96160 1.597973e-137 1.440413e-133
## ENSG00000101347 12703.3871 3.618232 0.1499441 24.13054 1.195378e-128 6.620010e-125
## ENSG00000120129 3409.0294 2.871326 0.1190334 24.12201 1.468829e-128 6.620010e-125
## ENSG00000189221 2341.7673 3.230629 0.1373644 23.51868 2.627083e-122 9.472209e-119
## ENSG00000211445 12285.6151 3.552999 0.1589971 22.34631 1.311440e-110 3.940441e-107
Keep it simple
Replicate
Avoid confounding experimental factors with other factors
Be aware of batch effects
HapMap samples from one facility, ordered by date of processing.
Confounding factors
Artifacts of your particular protocols
Axes of variation
Application-specific, e.g.,
Alignment
Splice-aware aligners (and Bioconductor wrappers)
Reduction to ‘count tables’
GenomicAlignments::summarizeOverlaps()
Rsubread::featureCount()
Unique statistical aspects
Summarization
Counts per se, rather than a summary (RPKM, FPKM, …), are relevant for analysis
Normalization
Detail
Appropriate error model
Pre-filtering
Borrowing information
‘Annotation’ packages
‘org’: map between gene identifiers; also GO.db, KEGGREST
library(org.Hs.eg.db)
ttbl <- head(res[order(res$padj),]) # 'top table' by p-adj
(ensid <- rownames(ttbl))
## [1] "ENSG00000152583" "ENSG00000165995" "ENSG00000101347" "ENSG00000120129" "ENSG00000189221"
## [6] "ENSG00000211445"
mapIds(org.Hs.eg.db, ensid, "SYMBOL", "ENSEMBL")
## ENSG00000152583 ENSG00000165995 ENSG00000101347 ENSG00000120129 ENSG00000189221 ENSG00000211445
## "SPARCL1" "CACNB2" "SAMHD1" "DUSP1" "MAOA" "GPX3"
select(org.Hs.eg.db, ensid, c("SYMBOL", "GENENAME"), "ENSEMBL")
## 'select()' returned 1:1 mapping between keys and columns
## ENSEMBL SYMBOL GENENAME
## 1 ENSG00000152583 SPARCL1 SPARC-like 1 (hevin)
## 2 ENSG00000165995 CACNB2 calcium channel, voltage-dependent, beta 2 subunit
## 3 ENSG00000101347 SAMHD1 SAM domain and HD domain 1
## 4 ENSG00000120129 DUSP1 dual specificity phosphatase 1
## 5 ENSG00000189221 MAOA monoamine oxidase A
## 6 ENSG00000211445 GPX3 glutathione peroxidase 3
columns(org.Hs.eg.db)
## [1] "ACCNUM" "ALIAS" "ENSEMBL" "ENSEMBLPROT" "ENSEMBLTRANS" "ENTREZID"
## [7] "ENZYME" "EVIDENCE" "EVIDENCEALL" "GENENAME" "GO" "GOALL"
## [13] "IPI" "MAP" "OMIM" "ONTOLOGY" "ONTOLOGYALL" "PATH"
## [19] "PFAM" "PMID" "PROSITE" "REFSEQ" "SYMBOL" "UCSCKG"
## [25] "UNIGENE" "UNIPROT"
‘TxDb’
## gene models, organized by entrez identifier
library(TxDb.Hsapiens.UCSC.hg19.knownGene)
txdb <- TxDb.Hsapiens.UCSC.hg19.knownGene
## from Ensembl to Entrez identifiers
egid <- mapIds(org.Hs.eg.db, ensid, "ENTREZID", "ENSEMBL")
transcriptsBy(txdb, "gene")[egid]
## GRangesList object of length 6:
## $8404
## GRanges object with 4 ranges and 2 metadata columns:
## seqnames ranges strand | tx_id tx_name
## <Rle> <IRanges> <Rle> | <integer> <character>
## [1] chr4 [88394488, 88450524] - | 19594 uc011cdc.2
## [2] chr4 [88394488, 88450655] - | 19595 uc003hqs.4
## [3] chr4 [88394488, 88450655] - | 19596 uc010ikm.3
## [4] chr4 [88394488, 88450655] - | 19597 uc011cdd.2
##
## ...
## <5 more elements>
## -------
## seqinfo: 93 sequences (1 circular) from hg19 genome
library(AnnotationHub)
hub = AnnotationHub()
query(hub, c("ensembl", "gtf", "release-83"))
Genomic Ranges: GenomicRanges
A ton of functionality, especially findOverlaps()
gr <- GRanges("chr1",
IRanges(c(1000, 2000, 3000), width=100),
strand=c("+", "-", "*"),
score=c(10, 20, 30))
gr
## GRanges object with 3 ranges and 1 metadata column:
## seqnames ranges strand | score
## <Rle> <IRanges> <Rle> | <numeric>
## [1] chr1 [1000, 1099] + | 10
## [2] chr1 [2000, 2099] - | 20
## [3] chr1 [3000, 3099] * | 30
## -------
## seqinfo: 1 sequence from an unspecified genome; no seqlengths
Data / metadata integration: SummarizedExperiment
Very easy to coordinate data manipulation – avoid those embarassing ‘off-by-one’ and other errors!
library(airway)
data(airway)
airway
## class: RangedSummarizedExperiment
## dim: 64102 8
## metadata(1): ''
## assays(1): counts
## rownames(64102): ENSG00000000003 ENSG00000000005 ... LRG_98 LRG_99
## rowRanges metadata column names(0):
## colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
## colData names(9): SampleName cell ... Sample BioSample
Efficient R programming
*apply()
are forms of iteration, not vectorizationR works best when memory is pre-allocated
Worst: no pre-allocation, no vectorization; scales quadratically with number of elements
result <- integer()
for (i in 1:10)
result[i] = sqrt(i)
Better: pre-allocate and fill; scales linearly with number of elements, but at the interpretted level
result <- integer(10)
for (i in 1:10)
result[[i]] = sqrt(i)
### same as the much more compact, expressive, and robust...
result <- sapply(1:10, sqrt)
Best: vectorize; scales linearly, but at the compiled level so 100x faster
result <- sqrt(1:10)
Parallel evaluation: BiocParallel
lapply
-likeDifferent ‘back-ends’, e.g., cores on a computer; computers in a cluster; instances in a cloud
library(BiocParallel)
system.time({
res <- lapply(1:8, function(i) { Sys.sleep(1); i })
})
## user system elapsed
## 0.001 0.000 8.011
system.time({
res <- bplapply(1:8, function(i) { Sys.sleep(1); i })
})
## user system elapsed
## 0.030 0.080 4.103
In Bioc-devel
X <- list(1, "2", 3)
res <- bptry(bplapply(X, sqrt))
X <- list(1, 2, 3)
res <- bplapply(X, sqrt, BPREDO=res)
Scripts
Vignettes
Light weight / accessible: R-flavored markdown
---
title: "A title"
author: "An Author"
vignette: >
% \VignetteEngine{knitr::rmarkdown}
---
# Heading
## Sub-heading
Some text.
```r
x <- rnorm(1000)
plot(x)
```
![](Bioc-Intro_files/figure-html/r-code-1.png)
Check out the knitr package!
Packages
Standard on-disk representation
/MyPackage
/MyPackage/DESCRIPTION
/MyPackage/NAMESPACE
/MyPackage/R/fun_one.R
/MyPackage/R/fun_another.R
/MyPackage/vignettes
Very easy to share, e.g., github
Individuals
Annual conference: https://bioconductor.org/BioC2016
sessionInfo()
## R version 3.2.3 Patched (2016-01-28 r70038)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 14.04.4 LTS
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
## [4] LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats4 parallel stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] BiocParallel_1.4.3 AnnotationHub_2.2.3
## [3] TxDb.Hsapiens.UCSC.hg19.knownGene_3.2.2 GenomicFeatures_1.22.12
## [5] org.Hs.eg.db_3.2.3 RSQLite_1.0.0
## [7] DBI_0.3.1 AnnotationDbi_1.32.3
## [9] DESeq2_1.10.1 RcppArmadillo_0.6.500.4.0
## [11] Rcpp_0.12.3 airway_0.104.0
## [13] SummarizedExperiment_1.0.2 Biobase_2.30.0
## [15] GenomicRanges_1.22.4 GenomeInfoDb_1.6.3
## [17] IRanges_2.4.7 S4Vectors_0.8.11
## [19] BiocGenerics_0.16.1 ggplot2_2.0.0
## [21] ENAR2016_0.0.1 BiocStyle_1.8.0
##
## loaded via a namespace (and not attached):
## [1] httr_1.1.0 splines_3.2.3 Formula_1.2-1
## [4] shiny_0.13.0 interactiveDisplayBase_1.8.0 latticeExtra_0.6-28
## [7] Rsamtools_1.23.1 yaml_2.1.13 lattice_0.20-33
## [10] digest_0.6.9 RColorBrewer_1.1-2 XVector_0.10.0
## [13] colorspace_1.2-6 htmltools_0.3 httpuv_1.3.3
## [16] Matrix_1.2-3 plyr_1.8.3 XML_3.98-1.3
## [19] biomaRt_2.26.1 genefilter_1.52.1 zlibbioc_1.16.0
## [22] xtable_1.8-2 scales_0.3.0 annotate_1.48.0
## [25] mgcv_1.8-11 nnet_7.3-12 survival_2.38-3
## [28] magrittr_1.5 mime_0.4 evaluate_0.8
## [31] nlme_3.1-124 foreign_0.8-66 BiocInstaller_1.20.1
## [34] tools_3.2.3 formatR_1.2.1 stringr_1.0.0
## [37] munsell_0.4.2 locfit_1.5-9.1 cluster_2.0.3
## [40] lambda.r_1.1.7 Biostrings_2.38.4 futile.logger_1.4.1
## [43] grid_3.2.3 RCurl_1.95-4.7 labeling_0.3
## [46] bitops_1.0-6 rmarkdown_0.9.2 gtable_0.1.2
## [49] codetools_0.2-14 R6_2.1.2 GenomicAlignments_1.6.3
## [52] gridExtra_2.0.0 knitr_1.12.3 rtracklayer_1.30.2
## [55] Hmisc_3.17-1 futile.options_1.0.0 stringi_1.0-1
## [58] geneplotter_1.48.0 rpart_4.1-10 acepack_1.3-3.3