<?xml version="1.0" encoding="UTF-8" ?>
<!-- RSS generated by PHPBoost on Tue, 14 Apr 2026 10:44:37 +0200 -->

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Easy Guides]]></title>
		<atom:link href="https://www.sthda.com/english/syndication/rss/wiki/16" rel="self" type="application/rss+xml"/>
		<link>https://www.sthda.com</link>
		<description><![CDATA[Last articles of the category: RNA sequencing]]></description>
		<copyright>(C) 2005-2026 PHPBoost</copyright>
		<language>en</language>
		<generator>PHPBoost</generator>
		
		
		<item>
			<title><![CDATA[Introduction to RNA sequencing]]></title>
			<link>https://www.sthda.com/english/wiki/introduction-to-rna-sequencing</link>
			<guid>https://www.sthda.com/english/wiki/introduction-to-rna-sequencing</guid>
			<description><![CDATA[-=-]]></description>
			<pubDate>Tue, 11 Nov 2014 20:39:26 +0100</pubDate>
			
		</item>
		
		<item>
			<title><![CDATA[RNA-Seq differential expression work flow using DESeq2]]></title>
			<link>https://www.sthda.com/english/wiki/rna-seq-differential-expression-work-flow-using-deseq2</link>
			<guid>https://www.sthda.com/english/wiki/rna-seq-differential-expression-work-flow-using-deseq2</guid>
			<description><![CDATA[<!-- START HTML -->

            
  <!--====================== start from here when you copy to sthda================-->  
  <div id="rdoc">



<div id="TOC">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#input-data">Input data</a></li>
<li><a href="#aligning-reads-to-a-reference">Aligning reads to a reference</a></li>
<li><a href="#example-bam-files">Example BAM files</a></li>
<li><a href="#counting-reads-in-genes">Counting reads in genes</a><ul>
<li><a href="#preparing-gene-models-from-gff-files">Preparing gene models from GFF files</a></li>
<li><a href="#reads-counting">Reads counting</a></li>
<li><a href="#summarizedexperiment-object-output-of-counting">SummarizedExperiment object : Output of counting</a></li>
</ul></li>
<li><a href="#the-deseqdataset-column-metadata-and-the-design-formula">The DESeqDataSet, column metadata, and the design formula</a></li>
<li><a href="#collapsing-technical-replicates">Collapsing technical replicates</a></li>
<li><a href="#running-the-deseq2-pipeline">Running the DESeq2 pipeline</a><ul>
<li><a href="#preparing-the-data-object-for-the-analysis-of-interest">Preparing the data object for the analysis of interest</a></li>
<li><a href="#running-the-pipeline">Running the pipeline</a></li>
<li><a href="#inspecting-the-results-table">Inspecting the results table</a></li>
<li><a href="#other-comparisons">Other comparisons</a></li>
<li><a href="#adding-gene-names">Adding gene names</a></li>
</ul></li>
<li><a href="#further-points">Further points</a><ul>
<li><a href="#multiple-testing">Multiple testing</a></li>
<li><a href="#diagnostic-plot">Diagnostic plot</a></li>
<li><a href="#independent-filtering">Independent filtering</a></li>
<li><a href="#exporting-results">Exporting results</a></li>
<li><a href="#gene-set-enrichment-analysis">Gene-set enrichment analysis</a></li>
</ul></li>
<li><a href="#working-with-rlog-transformed-data">Working with rlog-transformed data</a><ul>
<li><a href="#the-rlog-transform">The rlog transform</a></li>
<li><a href="#sample-distances">Sample distances</a></li>
<li><a href="#gene-clustering">Gene clustering</a></li>
<li><a href="#going-further">Going further</a></li>
</ul></li>
<li><a href="#see-also">See also</a></li>
<li><a href="#session-info">Session Info</a></li>
</ul>
</div>

<hr />
<p><span class="warning"> This analysis was performed using R (ver. 3.1.0). </span></p>
<div id="introduction" class="section level2">
<h2>Introduction</h2>
<p>One of the aim of RNAseq data analysis is the detection of differentially expressed genes. The package <a href="http://www.bioconductor.org/packages/release/bioc/html/DESeq2.html">DESeq2</a> provides methods to test for differential expression analysis.</p>
<p>This document presents an RNAseq differential expression workflow. We will start from the FASTQ files, align to the reference genome, prepare gene expression values as a count table by counting the sequenced fragments, perform differential gene expression analysis, and visually explore the results.</p>
</div>
<div id="input-data" class="section level2">
<h2>Input data</h2>
<p>We will use publicly available data from the article by <strong>Felix Haglund et al., J Clin Endocrin Metab 2012</strong>. The purpose of the experiment was to investigate the role of the estrogen receptor in parathyroid tumors. The investigators derived primary cultures of parathyroid adenoma cells from 4 patients. These primary cultures were treated with diarylpropionitrile (DPN), an estrogen receptor beta agonist, or with 4-hydroxytamoxifen (OHT). RNA was extracted at 24 hours and 48 hours from cultures under treatment and control.</p>
<p><span class="success"> Part of the data from this experiment is provided in the Bioconductor data package <strong>parathyroidSE</strong>. </span></p>
</div>
<div id="aligning-reads-to-a-reference" class="section level2">
<h2>Aligning reads to a reference</h2>
<p>What we get from the sequencing machine is a set of FASTQ files that contain the nucleotide sequence of each read and a quality score at each position. These reads must first be aligned to a reference genome or transcriptome. It is important to know if the sequencing experiment was single-end or paired-end, as the alignment software will require the user to specify both FASTQ files for a paired-end experiment. The output of this alignment step is commonly stored in a file format called <a href="http://samtools.github.io/hts-specs">BAM</a>.</p>
<p>Here we use the <a href="http://tophat.cbcb.umd.edu/">TopHat2</a> spliced alignment software in combination with the Bowtie index available at the <a href="http://ccb.jhu.edu/software/tophat/igenomes.shtml">Illumina iGenomes</a>.</p>
<p>For example, the paired-end RNA-Seq reads for the <a href="http://bioconductor.org/packages/release/data/experiment/html/parathyroidSE.html">parathyroidSE</a> package were aligned using TopHat2 with 8 threads, with the call:</p>
<p><span class="bash"> tophat2 -o file_tophat_out -p 8 path/to/genome file_1.fastq file_2.fastq samtools sort -n file_tophat_out/accepted_hits.bam _sorted </span></p>
<p><span class="success"> The second line sorts the reads by name rather than by genomic position, which is necessary for counting paired-end reads within Bioconductor. This command uses the <a href="http://samtools.sourceforge.net">SAMtools software</a>. </span></p>
<p>The BAM files for a number of sequencing runs can then be used to generate count matrices, as described in the following section.</p>
</div>
<div id="example-bam-files" class="section level2">
<h2>Example BAM files</h2>
<p>We will use BAM files from <strong>parathyroidSE</strong> package to demonstrate how a count table can be constructed from BAM files.</p>
<pre class="r"><code>library( "parathyroidSE" )
#Find extdata
extDataDir <- system.file("extdata", package = "parathyroidSE", mustWork = TRUE)
list.files( extDataDir )</code></pre>
<pre><code>## [1] "conversion.txt"             "GSE37211_series_matrix.txt" "SRR479052.bam"              "SRR479053.bam"             
## [5] "SRR479054.bam"</code></pre>
<p>Typically, we have a table with experimental meta data for our samples. For these three files, it is as follows:</p>
<pre class="r"><code>#Sample tables
sampleTable <- data.frame(
   sampleName = c( "Ctrl_24h_1", "Ctrl_48h_1", "DPN_24h_1" ),
   fileName = c( "SRR479052.bam", "SRR479053.bam",  "SRR479054.bam" ),
   treatment =  c( "Control", "Control", "DPN" ),
   time = c( "24h", "48h", "24h" ) )
#This is how the sample table should look like
sampleTable</code></pre>
<pre><code>##   sampleName      fileName treatment time
## 1 Ctrl_24h_1 SRR479052.bam   Control  24h
## 2 Ctrl_48h_1 SRR479053.bam   Control  48h
## 3  DPN_24h_1 SRR479054.bam       DPN  24h</code></pre>
<p>Construct the full paths to the files we want to perform the counting operation on:</p>
<pre class="r"><code>bamFiles <- file.path( extDataDir, sampleTable$fileName )
bamFiles</code></pre>
<pre><code>## [1] "/Library/Frameworks/R.framework/Versions/3.1/Resources/library/parathyroidSE/extdata/SRR479052.bam"
## [2] "/Library/Frameworks/R.framework/Versions/3.1/Resources/library/parathyroidSE/extdata/SRR479053.bam"
## [3] "/Library/Frameworks/R.framework/Versions/3.1/Resources/library/parathyroidSE/extdata/SRR479054.bam"</code></pre>
<p>We can peek into one of the BAM files to see the naming style of the sequences (chromosomes). Here we use the <strong>BamFile</strong> function from the <strong>Rsamtools</strong> package.</p>
<pre class="r"><code>library( "Rsamtools" )
seqinfo( BamFile( bamFiles[1] ) )</code></pre>
<pre><code>## Seqinfo of length 25
## seqnames seqlengths isCircular genome
## 1         249250621       <NA>   <NA>
## 2         243199373       <NA>   <NA>
## 3         198022430       <NA>   <NA>
## 4         191154276       <NA>   <NA>
## 5         180915260       <NA>   <NA>
## ...             ...        ...    ...
## 21         48129895       <NA>   <NA>
## 22         51304566       <NA>   <NA>
## X         155270560       <NA>   <NA>
## Y          59373566       <NA>   <NA>
## MT            16569       <NA>   <NA></code></pre>
<p><span class="success">
We want to make sure that these sequence names are the same style as that of the gene models we will obtain in the next section. </span></p>
</div>
<div id="counting-reads-in-genes" class="section level2">
<h2>Counting reads in genes</h2>
<p>To count how many read map to each gene, we need transcript annotation. Download the current GTF file with <a href="ftp://ftp.ensembl.org/pub/release-76/gtf/homo_sapiens/">human gene annotation from Ensembl</a>.</p>
<p>From this file, the function <strong>makeTranscriptDbFromGFF</strong> from the <strong>GenomicFeatures</strong> package constructs a database of all annotated transcripts.</p>
<p>For this lab you can use the truncated version of this file, called <a href="http://www.bioconductor.org/help/course-materials/2014/BioC2014/Homo_sapiens.GRCh37.75.subset.gtf.gz">Homo_sapiens.GRCh37.75.subset.gtf.gz</a>.</p>
<div id="preparing-gene-models-from-gff-files" class="section level3">
<h3>Preparing gene models from GFF files</h3>
<pre class="r"><code>library( "GenomicFeatures" )
#hse <- makeTranscriptDbFromGFF( "/path/to/your/genemodel_file.GTF", format="gtf" )
hse <- makeTranscriptDbFromGFF( "Homo_sapiens.GRCh37.75.subset.gtf", format="gtf" )
#Extract exons for each gene
exonsByGene <- exonsBy( hse, by="gene" )
exonsByGene</code></pre>
<pre><code>## GRangesList of length 100:
## $ENSG00000000003 
## GRanges with 13 ranges and 2 metadata columns:
##        seqnames               ranges strand   |   exon_id   exon_name
##           <Rle>            <IRanges>  <Rle>   | <integer> <character>
##    [1]        X [99883667, 99884983]      -   |      3038        <NA>
##    [2]        X [99885756, 99885863]      -   |      3039        <NA>
##    [3]        X [99887482, 99887565]      -   |      3040        <NA>
##    [4]        X [99887538, 99887565]      -   |      3041        <NA>
##    [5]        X [99888402, 99888536]      -   |      3042        <NA>
##    ...      ...                  ...    ... ...       ...         ...
##    [9]        X [99890555, 99890743]      -   |      3046        <NA>
##   [10]        X [99891188, 99891686]      -   |      3047        <NA>
##   [11]        X [99891605, 99891803]      -   |      3048        <NA>
##   [12]        X [99891790, 99892101]      -   |      3049        <NA>
##   [13]        X [99894942, 99894988]      -   |      3050        <NA>
## 
## ...
## <99 more elements>
## ---
## seqlengths:
##   7 12  2  6 16  4  3  1 17  8 19  X 11  9 20
##  NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA</code></pre>
<p>
</p>
<ul>
<li>Note that gene models can also be prepared directly from BioMart :</li>
</ul>
<p><br/></p>
<pre class="r"><code>library( "GenomicFeatures" )
# takes ~10 min
txdb <- makeTranscriptDbFromBiomart( biomart="ensembl",
                                    dataset="hsapiens_gene_ensembl" )
exonsByGene <- exonsBy( txdb, by="gene" )</code></pre>
<p><br/></p>
<p><span class="warning">Use <strong>saveDb()</strong> to only do this once. Use <strong>loadDb()</strong> to load the database next time.</span></p>
<p>
</p>
<p><span class="success"><strong>library(TxDb.Hsapiens.UCSC.hg19.knownGene)</strong> is also an ready to go option for gene models.</span> 
</p>
<ul>
<li>To convert from <code>chrX</code> to <code>X</code> and back:</li>
</ul>
<pre class="r"><code>seqlevelsStyle(gr) <- "NCBI"
seqlevelsStyle(gr) <- "UCSC"</code></pre>
<p>
</p>
</div>
<div id="reads-counting" class="section level3">
<h3>Reads counting</h3>
<p><br/></p>
<p>The function <strong>summarizeOverlaps</strong> from the <strong>GenomicAlignments</strong> package will do this. <br/></p>
<pre class="r"><code>library( "GenomicAlignments" )
se <- summarizeOverlaps( exonsByGene, BamFileList( bamFiles ), mode="Union",
  singleEnd=FALSE, ignore.strand=TRUE, fragments=TRUE )</code></pre>
<p>
</p>
<pre class="success"><code>We use the counting mode "Union", which indicates that those reads which overlap any portion of exactly one feature are counted. As this experiment produced paired-end reads, we specify singleEnd =FALSE. As protocol was not strand-specific, we specify ignore.strand = TRUE. fragments = TRUE indicates that we also want to count reads with unmapped pairs. This last argument is only for use with paired-end experiments.</code></pre>
<p>
</p>
<p><span class="warning"> Details on how to read from the BAM files can be specified using the <strong>BamFileList</strong> function. For example, to control the memory, we could have specified that batches of <strong>2 000 000</strong> reads should be read at a time: <br/></p>
<pre class="r"><code>BamFileList( bamFiles, yieldSize = 2000000 )</code></pre>
<p></span></p>
<p>
</p>
</div>
<div id="summarizedexperiment-object-output-of-counting" class="section level3">
<h3>SummarizedExperiment object : Output of counting</h3>
<p>We investigate the resulting <strong>SummarizedExperiment class</strong> by looking at the counts in the <strong>assay</strong> slot, the phenotypic data about the samples in <strong>colData</strong> slot (in this case an empty <strong>DataFrame</strong>), and the data about the genes in the <strong>rowData</strong> slot.</p>
<p>Figure 1 explains the basic structure of the <strong>SummarizedExperiment</strong> class.</p>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-summarizeexperiment-diagram.png" title="plot of chunk summarizeexperiment-diagram" alt="plot of chunk summarizeexperiment-diagram" width="288" /></p>
<pre class="r"><code># SummarizedExperiment
se</code></pre>
<pre><code>## class: SummarizedExperiment 
## dim: 100 3 
## exptData(0):
## assays(1): counts
## rownames(100): ENSG00000000003 ENSG00000000005 ... ENSG00000005469 ENSG00000005471
## rowData metadata column names(0):
## colnames(3): SRR479052.bam SRR479053.bam SRR479054.bam
## colData names(0):</code></pre>
<pre class="r"><code># Count data
head( assay(se) )</code></pre>
<pre><code>##                 SRR479052.bam SRR479053.bam SRR479054.bam
## ENSG00000000003             0             0             1
## ENSG00000000005             0             0             0
## ENSG00000000419             0             0             0
## ENSG00000000457             0             1             1
## ENSG00000000460             0             0             0
## ENSG00000000938             0             0             0</code></pre>
<pre class="r"><code>#Column sum
colSums( assay(se) )</code></pre>
<pre><code>## SRR479052.bam SRR479053.bam SRR479054.bam 
##            31            21            30</code></pre>
<pre class="r"><code>#Phenotypic data
colData(se)</code></pre>
<pre><code>## DataFrame with 3 rows and 0 columns</code></pre>
<pre class="r"><code>#Data about genes
rowData(se)</code></pre>
<pre><code>## GRangesList of length 100:
## $ENSG00000000003 
## GRanges with 13 ranges and 2 metadata columns:
##        seqnames               ranges strand   |   exon_id   exon_name
##           <Rle>            <IRanges>  <Rle>   | <integer> <character>
##    [1]        X [99883667, 99884983]      -   |      3038        <NA>
##    [2]        X [99885756, 99885863]      -   |      3039        <NA>
##    [3]        X [99887482, 99887565]      -   |      3040        <NA>
##    [4]        X [99887538, 99887565]      -   |      3041        <NA>
##    [5]        X [99888402, 99888536]      -   |      3042        <NA>
##    ...      ...                  ...    ... ...       ...         ...
##    [9]        X [99890555, 99890743]      -   |      3046        <NA>
##   [10]        X [99891188, 99891686]      -   |      3047        <NA>
##   [11]        X [99891605, 99891803]      -   |      3048        <NA>
##   [12]        X [99891790, 99892101]      -   |      3049        <NA>
##   [13]        X [99894942, 99894988]      -   |      3050        <NA>
## 
## ...
## <99 more elements>
## ---
## seqlengths:
##   7 12  2  6 16  4  3  1 17  8 19  X 11  9 20
##  NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA</code></pre>
<p><span class="success"> Note that the <strong>rowData</strong> slot is a <strong>GRangesList</strong>, which contains all the information about the exons for each gene, i.e., for each row of the count table. </span></p>
<p>The <strong>colData</strong> slot, so far empty, should contain all the meta data. We hence assign our sample table to it:</p>
<pre class="r"><code>#Column data
colData(se) <- DataFrame( sampleTable )</code></pre>
<p>We can extract columns from the <strong>colData</strong> using the <strong>$</strong> operator, and we can omit the <strong>colData</strong> to avoid extra keystrokes.</p>
<pre class="r"><code>colData(se)$treatment</code></pre>
<pre><code>## [1] Control Control DPN    
## Levels: Control DPN</code></pre>
<pre class="r"><code>se$treatment</code></pre>
<pre><code>## [1] Control Control DPN    
## Levels: Control DPN</code></pre>
<p>We can also use the sampleName table to name the columns of our data matrix:</p>
<pre class="r"><code>colnames(se) <- sampleTable$sampleName
head( assay(se) )</code></pre>
<pre><code>##                 Ctrl_24h_1 Ctrl_48h_1 DPN_24h_1
## ENSG00000000003          0          0         1
## ENSG00000000005          0          0         0
## ENSG00000000419          0          0         0
## ENSG00000000457          0          1         1
## ENSG00000000460          0          0         0
## ENSG00000000938          0          0         0</code></pre>
<pre class="success"><code>This SummarizedExperiment object se is then all we need to start our analysis.</code></pre>
</div>
</div>
<div id="the-deseqdataset-column-metadata-and-the-design-formula" class="section level2">
<h2>The DESeqDataSet, column metadata, and the design formula</h2>
<p>The data object class in <strong>DESeq2</strong> is the <strong>DESeqDataSet</strong>, which is built on top of the <strong>SummarizedExperiment</strong> class. One main differences is that the <strong>assay</strong> slot is instead accessed using the <strong>count</strong> accessor, and the values in this matrix must be non-negative integers.</p>
<p>A second difference is that the <strong>DESeqDataSet</strong> has an associated “design formula”. The design formula tells which variables in the column metadata table <strong>colData</strong> specify the experimental design and how these factors should be used in the analysis.</p>
<p>The simplest design formula for differential expression would be <code>~ condition</code>, where <strong>condition</strong> is a column in <code>colData(dds)</code> which specifies which of two (or more groups) the samples belong to.</p>
<p>For the parathyroid experiment, we will specify <code>~  patient + treatment</code>, which means that we want to test for the effect of treatment (the last factor), controlling for the effect of patient (the first factor).</p>
<p>We now use R’s <strong>data</strong> command to load a prepared <strong>SummarizedExperiment</strong> that was generated from the publicly available sequencing data files associated with the Haglund et al. paper, described on page 1. The steps we used to produce this object were equivalent to those you worked through in the previous Section, except that we used the complete set of samples and all reads.</p>
<pre class="r"><code>#Run data
data( "parathyroidGenesSE" )
se <- parathyroidGenesSE
colnames(se) <- se$run
# Check column data
colData(se)[1:5,1:4]</code></pre>
<pre><code>## DataFrame with 5 rows and 4 columns
##                   run experiment  patient treatment
##           <character>   <factor> <factor>  <factor>
## SRR479052   SRR479052  SRX140503        1   Control
## SRR479053   SRR479053  SRX140504        1   Control
## SRR479054   SRR479054  SRX140505        1       DPN
## SRR479055   SRR479055  SRX140506        1       DPN
## SRR479056   SRR479056  SRX140507        1       OHT</code></pre>
<p>Here we see that this object already contains an informative <strong>colData slot</strong>.</p>
<p>When you work with your own data, you will have to add the pertinent sample / phenotypic information for the experiment at this stage. We highly recommend keeping this information in a comma-separated value (CSV) or tab-separated value (TSV) file, which can be exported from an Excel spreadsheet, and the assign this to the <strong>colData</strong> slot, as shown in the previous section.</p>
<pre class="warning"><code>Make sure that the order of rows in your column data table matches the order of columns in the assay data slot.</code></pre>
<p><span class="success"> A bonus about the workflow we have shown above is that information about the gene models we used is included without extra effort. The <strong>str</strong> R function is used to compactly display the structure of the data in the list.
</span></p>
<pre class="r"><code>str( metadata( rowData(se) ) )</code></pre>
<pre><code>## List of 1
##  $ genomeInfo:List of 20
##   ..$ Db type                                 : chr "TranscriptDb"
##   ..$ Supporting package                      : chr "GenomicFeatures"
##   ..$ Data source                             : chr "BioMart"
##   ..$ Organism                                : chr "Homo sapiens"
##   ..$ Resource URL                            : chr "www.biomart.org:80"
##   ..$ BioMart database                        : chr "ensembl"
##   ..$ BioMart database version                : chr "ENSEMBL GENES 72 (SANGER UK)"
##   ..$ BioMart dataset                         : chr "hsapiens_gene_ensembl"
##   ..$ BioMart dataset description             : chr "Homo sapiens genes (GRCh37.p11)"
##   ..$ BioMart dataset version                 : chr "GRCh37.p11"
##   ..$ Full dataset                            : chr "yes"
##   ..$ miRBase build ID                        : chr NA
##   ..$ transcript_nrow                         : chr "213140"
##   ..$ exon_nrow                               : chr "737783"
##   ..$ cds_nrow                                : chr "531154"
##   ..$ Db created by                           : chr "GenomicFeatures package from Bioconductor"
##   ..$ Creation time                           : chr "2013-07-30 17:30:25 +0200 (Tue, 30 Jul 2013)"
##   ..$ GenomicFeatures version at creation time: chr "1.13.21"
##   ..$ RSQLite version at creation time        : chr "0.11.4"
##   ..$ DBSCHEMAVERSION                         : chr "1.0"</code></pre>
<p>Once we have our fully annotated <strong>SummerizedExperiment</strong> object, we can construct a DESeqDataSet object from it, which will then form the staring point of the actual <strong>DESeq2</strong> package</p>
<pre class="r"><code>library( "DESeq2" )
ddsFull <- DESeqDataSet( se, design = ~ patient + treatment )</code></pre>
<p><span class="warning"> Note that there are two alternative functions, <strong>DESeqDataSetFromMatrix</strong> and <strong>DESeqDataSetFromHTSeq</strong>, which allow you to get started in case you have your data not in the form of a <strong>SummarizedExperiment</strong> object, but either as a simple matrix of count values or as output files from the <strong>htseq-count</strong> script from the <strong>HTSeq</strong> Python package. </span></p>
</div>
<div id="collapsing-technical-replicates" class="section level2">
<h2>Collapsing technical replicates</h2>
<p>There are a number of samples which were sequenced in multiple runs. For example, sample <strong>SRS308873</strong> was sequenced twice.</p>
<pre class="r"><code>#as.data.frame forces R to show us the full list
head(as.data.frame( colData( ddsFull )[ ,c("sample","patient","treatment","time") ] ), 12)</code></pre>
<pre><code>##              sample patient treatment time
## SRR479052 SRS308865       1   Control  24h
## SRR479053 SRS308866       1   Control  48h
## SRR479054 SRS308867       1       DPN  24h
## SRR479055 SRS308868       1       DPN  48h
## SRR479056 SRS308869       1       OHT  24h
## SRR479057 SRS308870       1       OHT  48h
## SRR479058 SRS308871       2   Control  24h
## SRR479059 SRS308872       2   Control  48h
## SRR479060 SRS308873       2       DPN  24h
## SRR479061 SRS308873       2       DPN  24h
## SRR479062 SRS308874       2       DPN  48h
## SRR479063 SRS308875       2       OHT  24h</code></pre>
<p>A convenience function has been implemented to collapse, which can take an object, either <strong>SummarizedExperiment</strong> or <strong>DESeqDataSet</strong>, and a grouping factor, in this case the sample name, and return the object with the counts summed up for each unique sample. Optionally, we can provide a third argument, run, which can be used to paste together the names of the runs which were collapsed to create the new object.</p>
<pre class="success"><code>Note that dds$variable is equivalent to colData(dds)$variable.</code></pre>
<pre class="r"><code>ddsCollapsed <- collapseReplicates( ddsFull,
                                    groupby = ddsFull$sample,
                                    run = ddsFull$run )
head( as.data.frame( colData(ddsCollapsed)[ ,c("sample","runsCollapsed") ] ), 12 )</code></pre>
<pre><code>##              sample       runsCollapsed
## SRS308865 SRS308865           SRR479052
## SRS308866 SRS308866           SRR479053
## SRS308867 SRS308867           SRR479054
## SRS308868 SRS308868           SRR479055
## SRS308869 SRS308869           SRR479056
## SRS308870 SRS308870           SRR479057
## SRS308871 SRS308871           SRR479058
## SRS308872 SRS308872           SRR479059
## SRS308873 SRS308873 SRR479060,SRR479061
## SRS308874 SRS308874           SRR479062
## SRS308875 SRS308875 SRR479063,SRR479064
## SRS308876 SRS308876           SRR479065</code></pre>
<p>We can confirm that the counts for the new object are equal to the summed up counts of the columns that had the same value for the grouping factor:</p>
<pre class="r"><code>original <- rowSums( counts(ddsFull)[ , ddsFull$sample == "SRS308873" ] )
all( original == counts(ddsCollapsed)[ ,"SRS308873" ] )</code></pre>
<pre><code>## [1] TRUE</code></pre>
</div>
<div id="running-the-deseq2-pipeline" class="section level2">
<h2>Running the DESeq2 pipeline</h2>
<p>Here we will analyze a subset of the samples, namely those taken after 48 hours, with either control, DPN or OHT treatment, taking into account the multifactor design.</p>
<div id="preparing-the-data-object-for-the-analysis-of-interest" class="section level3">
<h3>Preparing the data object for the analysis of interest</h3>
<p>First we subset the relevant columns from the full dataset:</p>
<pre class="r"><code>dds <- ddsCollapsed[ , ddsCollapsed$time == "48h" ]</code></pre>
<p>Sometimes it is necessary to drop levels of the factors, in case that all the samples for one or more levels of a factor in the design have been removed. If time were included in the design formula, the following code could be used to take care of dropped levels in this column.</p>
<pre class="r"><code>dds$time <- droplevels( dds$time )</code></pre>
<p>It will be convenient to make sure that <strong>Control</strong> is the <strong>first</strong> level in the treatment factor, so that the default log2 fold changes are calculated as treatment over control and not the other way around. The function <strong>relevel</strong> achieves this:</p>
<pre class="r"><code>dds$treatment <- relevel( dds$treatment, "Control" )</code></pre>
<p>A quick check whether we now have the right samples:</p>
<pre class="r"><code>as.data.frame( colData(dds) )</code></pre>
<pre><code>##                 run experiment patient treatment time submission     study    sample       runsCollapsed
## SRS308866 SRR479053  SRX140504       1   Control  48h  SRA051611 SRP012167 SRS308866           SRR479053
## SRS308868 SRR479055  SRX140506       1       DPN  48h  SRA051611 SRP012167 SRS308868           SRR479055
## SRS308870 SRR479057  SRX140508       1       OHT  48h  SRA051611 SRP012167 SRS308870           SRR479057
## SRS308872 SRR479059  SRX140510       2   Control  48h  SRA051611 SRP012167 SRS308872           SRR479059
## SRS308874 SRR479062  SRX140512       2       DPN  48h  SRA051611 SRP012167 SRS308874           SRR479062
## SRS308876 SRR479065  SRX140514       2       OHT  48h  SRA051611 SRP012167 SRS308876           SRR479065
## SRS308878 SRR479067  SRX140516       3   Control  48h  SRA051611 SRP012167 SRS308878           SRR479067
## SRS308880 SRR479069  SRX140518       3       DPN  48h  SRA051611 SRP012167 SRS308880           SRR479069
## SRS308882 SRR479071  SRX140520       3       OHT  48h  SRA051611 SRP012167 SRS308882           SRR479071
## SRS308883 SRR479072  SRX140521       4   Control  48h  SRA051611 SRP012167 SRS308883           SRR479072
## SRS308885 SRR479074  SRX140523       4       DPN  48h  SRA051611 SRP012167 SRS308885 SRR479074,SRR479075
## SRS308887 SRR479077  SRX140525       4       OHT  48h  SRA051611 SRP012167 SRS308887 SRR479077,SRR479078</code></pre>
<p>In order to speed up some annotation steps below, it makes sense to remove genes which have zero counts for all samples. This can be done by simply indexing the <strong>dds</strong> object:</p>
<pre class="r"><code>dds <- dds[ rowSums( counts(dds) ) > 0 , ]</code></pre>
</div>
<div id="running-the-pipeline" class="section level3">
<h3>Running the pipeline</h3>
<p>Let’s recall what design we have specified:</p>
<pre class="r"><code>#design
design(dds)</code></pre>
<pre><code>## ~patient + treatment</code></pre>
<pre class="r"><code>#Run DESeq : Modeling counts with patient and treatment effects
dds <- DESeq(dds)</code></pre>
<pre class="success"><code>This function will print out a message for the various steps it performs. Briefly these are: the estimation of size factors (which control for differences in the library size of the sequencing experiments), the estimation of dispersion for each gene, and fitting a generalized linear model.</code></pre>
<p>A <strong>DESeqDataSet</strong> is returned which contains all the fitted information within it, and the following section describes how to extract out results tables of interest from this object.</p>
</div>
<div id="inspecting-the-results-table" class="section level3">
<h3>Inspecting the results table</h3>
<p>Calling <strong>results</strong> without any arguments will extract the estimated log2 fold changes and <strong>p</strong> values for the last variable in the design formula. If there are more than 2 levels for this variable – as is the case in this analysis – <strong>results</strong> will extract the results table for a comparison of the last level over the first level. The following section describes how to extract other comparisons.</p>
<pre class="r"><code>res <- results( dds )
res</code></pre>
<pre><code>## log2 fold change (MAP): treatment OHT vs Control 
## Wald test p-value: treatment OHT vs Control 
## DataFrame with 32082 rows and 6 columns
##                  baseMean log2FoldChange     lfcSE      stat    pvalue      padj
##                 <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000000003  613.8196      -0.044799   0.08787  -0.50983  0.610173    0.9837
## ENSG00000000005    0.5502      -0.568326   1.08754  -0.52258  0.601268        NA
## ENSG00000000419  304.0482       0.116118   0.09623   1.20668  0.227555        NA
## ENSG00000000457  183.5157       0.007441   0.12314   0.06042  0.951819        NA
## ENSG00000000460  207.4336       0.470836   0.14493   3.24867  0.001159        NA
## ...                   ...            ...       ...       ...       ...       ...
## ENSG00000271699   0.17125       -1.09753    0.9097  -1.20646   0.22764        NA
## ENSG00000271704   0.10233       -0.01414    0.7157  -0.01975   0.98424        NA
## ENSG00000271707   9.21112       -0.84445    0.4832  -1.74774   0.08051        NA
## ENSG00000271709   0.08257       -0.01108    0.6782  -0.01633   0.98697        NA
## ENSG00000271711   0.74835       -0.95188    1.0655  -0.89335   0.37167        NA</code></pre>
<p>As <strong>res</strong> is a <strong>DataFrame</strong> object, it carries metadata with information on the meaning of the columns:</p>
<pre class="r"><code>mcols(res, use.names=TRUE)</code></pre>
<pre><code>## DataFrame with 6 rows and 2 columns
##                        type                                      description
##                 <character>                                      <character>
## baseMean       intermediate                      the base mean over all rows
## log2FoldChange      results log2 fold change (MAP): treatment OHT vs Control
## lfcSE               results         standard error: treatment OHT vs Control
## stat                results         Wald statistic: treatment OHT vs Control
## pvalue              results      Wald test p-value: treatment OHT vs Control
## padj                results                             BH adjusted p-values</code></pre>
<p>The first column, <strong>baseMean</strong>, is a just the average of the normalized count values, dividing by size factors, taken over all samples. The remaining four columns refer to a specific <strong>contrast</strong>, namely the comparison of the levels <strong>DPN</strong> versus <strong>Control</strong> of the factor variable <strong>treatment</strong>.</p>
<p>See the help page for <strong>results</strong> (by typing <code>?results</code>) for information on how to obtain other contrasts.</p>
<p>The column <strong>log2FoldChange</strong> is the effect size estimate. It tells us how much the gene’s expression seems to have changed due to treatment with DPN in comparison to control. This value is reported on a logarithmic scale to base 2: for example, a log2 fold change of 1.5 means that the gene’s expression is increased by a multiplicative factor of <span class="math">2<sup>1.5</sup> ≈ 2.82</span>.</p>
<p>Of course, this estimate has an uncertainty associated with it, which is available in the column <strong>lfcSE</strong>, the standard error estimate for the log2 fold change estimate. The column <span class="math"><em>p</em></span> value indicates wether the observed difference between treatment and control is significantly different.</p>
<p><span class="warning"> We note that a subset of the <span class="math"><em>p</em></span> values in <strong>res</strong> are <strong>NA</strong> (“notavailable”). This is <strong>DESeq</strong>’s way of reporting that all counts for this gene were zero, and hence not test was applied. In addition, <span class="math"><em>p</em></span> values can be assigned <strong>NA</strong> if the gene was excluded from analysis because it contained an extreme count outlier. For more information, see the outlier detection section of the advanced vignette. </span></p>
<p>We can examine the counts and normalized counts for the gene with the smallest p value:</p>
<pre class="r"><code># SmallestPvalue
idx <- which.min(res$pvalue)
counts(dds)[idx, ]</code></pre>
<pre><code>## SRS308866 SRS308868 SRS308870 SRS308872 SRS308874 SRS308876 SRS308878 SRS308880 SRS308882 SRS308883 SRS308885 SRS308887 
##        95        62        30        24        13        21       276       357       112       388       404       296</code></pre>
<pre class="r"><code>#Normalization
counts(dds, normalized=TRUE)[ idx, ]</code></pre>
<pre><code>## SRS308866 SRS308868 SRS308870 SRS308872 SRS308874 SRS308876 SRS308878 SRS308880 SRS308882 SRS308883 SRS308885 SRS308887 
##     86.81     61.43     37.42     35.25     15.96     25.85    314.96    201.94    136.92    461.46    269.09    172.00</code></pre>
</div>
<div id="other-comparisons" class="section level3">
<h3>Other comparisons</h3>
<p>The results for a comparison of any two levels of a variable can be extracted using the <strong>contrast</strong> argument to <strong>results</strong>. The user should specify three values: The name of the variable, the name of the level in the numerator, and the name of the level in the denominator.</p>
<p>Here we extract results for the log2 of the fold change of DPN/Control:</p>
<pre class="r"><code>#Save result table
resOHT <- res
#Other comparisons
res <- results( dds, contrast = c("treatment", "DPN", "Control") )
res</code></pre>
<pre><code>## log2 fold change (MAP): treatment DPN vs Control 
## Wald test p-value: treatment DPN vs Control 
## DataFrame with 32082 rows and 6 columns
##                  baseMean log2FoldChange     lfcSE      stat    pvalue      padj
##                 <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000000003  613.8196       -0.01722   0.08665  -0.19868   0.84252    0.9775
## ENSG00000000005    0.5502       -0.10344   1.09363  -0.09458   0.92465        NA
## ENSG00000000419  304.0482       -0.01695   0.09517  -0.17807   0.85867    0.9811
## ENSG00000000457  183.5157       -0.09654   0.12138  -0.79533   0.42642    0.8945
## ENSG00000000460  207.4336        0.35004   0.14375   2.43497   0.01489    0.2762
## ...                   ...            ...       ...       ...       ...       ...
## ENSG00000271699   0.17125        -1.1391    0.9251   -1.2313    0.2182        NA
## ENSG00000271704   0.10233         0.5925    0.7547    0.7851    0.4324        NA
## ENSG00000271707   9.21112        -0.5099    0.4579   -1.1136    0.2655        NA
## ENSG00000271709   0.08257         0.5156    0.7112    0.7250    0.4685        NA
## ENSG00000271711   0.74835        -0.6649    1.0511   -0.6326    0.5270        NA</code></pre>
</div>
<div id="adding-gene-names" class="section level3">
<h3>Adding gene names</h3>
<p>Our result table only uses Ensembl gene IDs, but gene names may be more informative. Bioconductor’s annotation packages help with mapping various ID schemes to each other.</p>
<p>We load the annotation package <strong>org.Hs.eg.db</strong>:</p>
<pre class="r"><code>library( "org.Hs.eg.db" )</code></pre>
<p>This is the organism annotation package (“org”“) for <strong>Homo sapiens</strong> (”Hs“”), organized as an <strong>AnnotationDbi</strong> package (“db”“), using Entrez Gene IDs (”eg“) as primary key.</p>
<p>To get a list of all available key types, use</p>
<pre class="r"><code>columns(org.Hs.eg.db)</code></pre>
<pre><code>##  [1] "ENTREZID"     "PFAM"         "IPI"          "PROSITE"      "ACCNUM"       "ALIAS"        "CHR"         
##  [8] "CHRLOC"       "CHRLOCEND"    "ENZYME"       "MAP"          "PATH"         "PMID"         "REFSEQ"      
## [15] "SYMBOL"       "UNIGENE"      "ENSEMBL"      "ENSEMBLPROT"  "ENSEMBLTRANS" "GENENAME"     "UNIPROT"     
## [22] "GO"           "EVIDENCE"     "ONTOLOGY"     "GOALL"        "EVIDENCEALL"  "ONTOLOGYALL"  "OMIM"        
## [29] "UCSCKG"</code></pre>
<p>Converting IDs with the native functions from the <strong>AnnotationDbi</strong> package is currently a bit cumbersome, so we provide the following convenience function (without explaining how exactly it works):</p>
<pre class="r"><code>#ids = list of IDS
#fromKey = key type; toKey = key type we want to convert to
#db = the AnnotationDb object to use.
#ifMultiple = the argument specifies what to do if one source ID maps to several target IDs:
  #should the function return an NA or simply the first of the multiple IDs?
convertIDs <- function( ids, fromKey, toKey, db, ifMultiple=c( "putNA", "useFirst" ) ) {
   stopifnot( inherits( db, "AnnotationDb" ) )
   ifMultiple <- match.arg( ifMultiple )
   suppressWarnings( selRes <- AnnotationDbi::select( 
      db, keys=ids, keytype=fromKey, columns=c(fromKey,toKey) ) )
   if( ifMultiple == "putNA" ) {
      duplicatedIds <- selRes[ duplicated( selRes[,1] ), 1 ]   
      selRes <- selRes[ ! selRes[,1] %in% duplicatedIds, ] }
   return( selRes[ match( ids, selRes[,1] ), 2 ] )
}</code></pre>
<p>To convert the Ensembl IDs in the rownames of <strong>res</strong> to gene symbols and add them as a new column, we use:</p>
<pre class="r"><code>res$hgnc_symbol <- convertIDs( row.names(res), "ENSEMBL", "SYMBOL", org.Hs.eg.db )
res$entrezid <- convertIDs( row.names(res), "ENSEMBL", "ENTREZID", org.Hs.eg.db )
head(res, 4)</code></pre>
<pre><code>## log2 fold change (MAP): treatment DPN vs Control 
## Wald test p-value: treatment DPN vs Control 
## DataFrame with 4 rows and 8 columns
##                  baseMean log2FoldChange     lfcSE      stat    pvalue      padj hgnc_symbol    entrezid
##                 <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric> <character> <character>
## ENSG00000000003  613.8196       -0.01722   0.08665  -0.19868    0.8425    0.9775      TSPAN6        7105
## ENSG00000000005    0.5502       -0.10344   1.09363  -0.09458    0.9246        NA        TNMD       64102
## ENSG00000000419  304.0482       -0.01695   0.09517  -0.17807    0.8587    0.9811        DPM1        8813
## ENSG00000000457  183.5157       -0.09654   0.12138  -0.79533    0.4264    0.8945       SCYL3       57147</code></pre>
<pre class="success"><code>This conversion can be done from Ensembl BioMart web site.</code></pre>
</div>
</div>
<div id="further-points" class="section level2">
<h2>Further points</h2>
<div id="multiple-testing" class="section level3">
<h3>Multiple testing</h3>
<p><strong>DESeq2</strong> uses the so-called Benjamini-Hochberg (BH) adjustment for multiple testing problem; in brief, this method calculates for each gene an <strong>adjusted <span class="math"><em>p</em></span> value</strong> which answers the following question: if one called significant all genes with a <span class="math"><em>p</em></span> value less than or equal to this gene’s <span class="math"><em>p</em></span> value threshold, what would be the fraction of false positives (the <strong>false discovery rate</strong>, FDR) among them (in the sense of the calculation outlined above)? These values, called the BH-adjusted <span class="math"><em>p</em></span> values, are given in the column <strong>padj</strong> of the <strong>results</strong> object.</p>
<p>Hence, if we consider a fraction of 10% false positives acceptable, we can consider all genes with an <strong>adjusted</strong> <span class="math"><em>p</em></span> value below 10%=0.1 as significant. How many such genes are there?</p>
<pre class="r"><code>sum( res$padj < 0.1, na.rm=TRUE )</code></pre>
<pre><code>## [1] 249</code></pre>
<p>We subset the results table to these genes and then sort it by the log2 fold change estimate to get the significant genes with the strongest down-regulation:</p>
<pre class="r"><code>resSig <- subset(res, res$padj < 0.1 )
head( resSig[ order( resSig$log2FoldChange ), ], 4)</code></pre>
<pre><code>## log2 fold change (MAP): treatment DPN vs Control 
## Wald test p-value: treatment DPN vs Control 
## DataFrame with 4 rows and 8 columns
##                  baseMean log2FoldChange     lfcSE      stat    pvalue      padj hgnc_symbol    entrezid
##                 <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric> <character> <character>
## ENSG00000163631     233.3        -0.9307    0.2842    -3.275 1.058e-03   0.05817         ALB         213
## ENSG00000119946     151.6        -0.6903    0.1566    -4.408 1.041e-05   0.00246       CNNM1       26507
## ENSG00000041982    1377.0        -0.6859    0.1845    -3.717 2.018e-04   0.02045         TNC        3371
## ENSG00000155111     530.9        -0.6756    0.2109    -3.203 1.359e-03   0.06850       CDK19       23097</code></pre>
<p>and with the strongest upregulation :</p>
<pre class="r"><code>head( resSig[ order( -resSig$log2FoldChange ), ], 4)</code></pre>
<pre><code>## log2 fold change (MAP): treatment DPN vs Control 
## Wald test p-value: treatment DPN vs Control 
## DataFrame with 4 rows and 8 columns
##                  baseMean log2FoldChange     lfcSE      stat    pvalue      padj hgnc_symbol    entrezid
##                 <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric> <character> <character>
## ENSG00000092621     558.5         0.9002    0.1258     7.158 8.191e-13 2.628e-09       PHGDH       26227
## ENSG00000101255     255.1         0.8860    0.1694     5.229 1.706e-07 2.346e-04       TRIB3       57761
## ENSG00000103257     168.5         0.8259    0.1644     5.024 5.064e-07 3.249e-04      SLC7A5        8140
## ENSG00000156414     142.8         0.7582    0.1661     4.564 5.025e-06 1.547e-03       TDRD9      122402</code></pre>
</div>
<div id="diagnostic-plot" class="section level3">
<h3>Diagnostic plot</h3>
<div id="ma-plot" class="section level4">
<h4>MA plot</h4>
<p>A so-called MA plot provides a useful overview for an experiment with a two-group comparison:</p>
<pre class="r"><code>plotMA( res, ylim = c(-3, 3) )</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_MA.png" title="plot of chunk beginner_MA" alt="plot of chunk beginner_MA" width="288" /></p>
<p>The MA-plot represents each gene with a dot. The <span class="math"><em>x</em></span> axis is the average expression over all samples, the <span class="math"><em>y</em></span> axis the log2 fold change of normalized counts (i.e the average of counts normalized by size factor) between treatment and control. Genes with an adjusted <span class="math"><em>p</em></span> value below a threshold (here 0.1, the default) are shown in red.</p>
<pre class="success"><code>This plot demonstrates that only genes with a large average normalized count contain sufficient information to yield a significant call.</code></pre>
<p>
</p>
</div>
<div id="dispersion-plot" class="section level4">
<h4>Dispersion plot</h4>
<p>Also note DESeq2 shrinkage estimation of log fold changes (LFCs): When count values are too low to allow an accurate estimate of the LFC, the value is “shrunken”" towards zero to avoid that these values, which otherwise would frequently be unrealistically large, dominate the top-ranked log fold change. Whether a gene is called significant depends not only on its LFC but also on its within-group variability, which DESeq2 quantifies as the <strong>dispersion</strong>. For strongly expressed genes, the dispersion can be understood as a squared coefficient of variation: a dispersion value of 0.01 means that the gene’s expression tends to differ by typically <span class="math">$\sqrt{0.01}=10\%$</span> between samples of the same treatment group. For weak genes, the Poisson noise is an additional source of noise, which is added to the dispersion. 
 The function <strong>plotDispEsts</strong> visualizes DESeq2’s dispersion estimates:</p>
<pre class="r"><code>plotDispEsts( dds, ylim = c(1e-6, 1e1) )</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_dispPlot.png" title="plot of chunk beginner_dispPlot" alt="plot of chunk beginner_dispPlot" width="384" /></p>
<p>The black points are the dispersion estimates for each gene as obtained by considering the information from each gene separately. Unless one has many samples, these values fluctuate strongly around their true values. Therefore, we fit the red trend line, which shows the dispersions’ dependence on the mean, and then shrink each gene’s estimate towards the red line to obtain the final estimates (blue points) that are then used in the hypothesis test. The blue circles above the main “cloud”" of points are genes which have high gene-wise dispersion estimates which are labelled as dispersion outliers. These estimates are therefore not shrunk toward the fitted trend line.</p>
</div>
<div id="histogram-of-the-p-value" class="section level4">
<h4>Histogram of the p-value</h4>
<pre class="r"><code>hist( res$pvalue, breaks=20, col="grey" )</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_pvalHist.png" title="plot of chunk beginner_pvalHist" alt="plot of chunk beginner_pvalHist" width="288" /></p>
</div>
</div>
<div id="independent-filtering" class="section level3">
<h3>Independent filtering</h3>
<p>The MA plot highlights an important property of RNA-Seq data. <strong>For weakly expressed genes, we have no chance of seeing differential expression</strong>, because the low read counts suffer from so high Poisson noise that any biological effect is drowned in the uncertainties from the read counting. We can also show this by examining the ratio of small <span class="math"><em>p</em></span> values (say, less than, 0.01) for genes binned by mean normalized count:</p>
<pre class="r"><code># create bins using the quantile function
qs <- c( 0, quantile( res$baseMean[res$baseMean > 0], 0:7/7 ) )
# "cut" the genes into the bins
bins <- cut( res$baseMean, qs )
# rename the levels of the bins using the middle point
levels(bins) <- paste0("~",round(.5*qs[-1] + .5*qs[-length(qs)]))
# calculate the ratio of p values less than .01 for each bin
ratios <- tapply( res$pvalue, bins, function(p) mean( p < .01, na.rm=TRUE ) )
# plot these ratios
barplot(ratios, xlab="mean normalized count", ylab="ratio of small p values")</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_ratioSmallP.png" title="plot of chunk beginner_ratioSmallP" alt="plot of chunk beginner_ratioSmallP" width="480" /></p>
<p><span class="success"> At first sight, there may seem to be little benefit in filtering out these genes. After all, the test found them to be non-significant anyway. However, these genes have an influence on the multiple testing adjustment, whose performance improves if such genes are removed. By removing the weakly-expressed genes from the input to the FDR procedure, we can find more genes to be significant among those which we keep, and so improved the power of our test. This approach is known as <strong>independent filtering</strong>. </span></p>
<p>The DESeq software automatically performs independent filtering which maximizes the number of genes which will have adjusted <span class="math"><em>p</em></span> value less than a critical value (by default, <strong>alpha</strong> is set to 0.1). This automatic independent filtering is performed by, and can be controlled by, the <strong>results</strong> function. We can observe how the number of rejections changes for various cutoffs based on mean normalized count. The following optimal threshold and table of possible values is stored as an <strong>attribute</strong> of the results object.</p>
<pre class="r"><code>attr(res,"filterThreshold")</code></pre>
<pre><code>##   70% 
## 126.9</code></pre>
<pre class="r"><code>plot(attr(res,"filterNumRej"),type="b",
     xlab="quantiles of &amp;#39;baseMean&amp;#39;",
     ylab="number of rejections")</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_filtByMean.png" title="plot of chunk beginner_filtByMean" alt="plot of chunk beginner_filtByMean" width="288" /></p>
<p><span class="warning"> The term <strong>independent</strong> highlights an important caveat. Such filtering is permissible only if the filter criterion is independent of the actual test statistic. Otherwise, the filtering would invalidate the test and consequently the assumptions of the BH procedure. This is why we filtered on the average over <strong>all</strong> samples: this filter is blind to the assignment of samples to the treatment and control group and hence independent. </span></p>
</div>
<div id="exporting-results" class="section level3">
<h3>Exporting results</h3>
<p>You can easily save the results table in a CSV file, which you can then load with a spreadsheet program such as Excel:</p>
<pre class="r"><code>res[1:2,]
write.csv( as.data.frame(res), file="results.csv" )</code></pre>
</div>
<div id="gene-set-enrichment-analysis" class="section level3">
<h3>Gene-set enrichment analysis</h3>
<p>Do the genes with a strong up- or down-regulation have something in common? We perform next a gene-set enrichment analysis (GSEA) to examine this question.</p>
<p>We here present a relatively simplistic approach, to demonstrate the basic ideas, but note that a more careful treatment will be needed for more definitive results.</p>
<p>We use the gene sets in the Reactome database:</p>
<pre class="r"><code>#source("http://bioconductor.org/biocLite.R")
#biocLite("reactome.db")
library( "reactome.db" )</code></pre>
<p>This database works with Entrez IDs, so we will need the <strong>entrezid</strong> column that we added earlier to the <strong>res</strong> object.</p>
<p>First, we subset the results table, <strong>res</strong>, to only those genes for which the Reactome database has data (i.e, whose Entrez ID we find in the respective key column of <strong>reactome.db</strong> and for which the DESeq2 test gave an adjusted <span class="math"><em>p</em></span> value that was not <strong>NA</strong>.</p>
<pre class="r"><code>res2 <- res[ res$entrezid %in% keys( reactome.db, "ENTREZID" ) &amp; !is.na( res$padj ) , ]
head(res2)</code></pre>
<pre><code>## log2 fold change (MAP): treatment DPN vs Control 
## Wald test p-value: treatment DPN vs Control 
## DataFrame with 6 rows and 8 columns
##                  baseMean log2FoldChange     lfcSE      stat    pvalue      padj hgnc_symbol    entrezid
##                 <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric> <character> <character>
## ENSG00000000419     304.0      -0.016946   0.09517  -0.17807    0.8587    0.9811        DPM1        8813
## ENSG00000001084     312.0       0.039811   0.10228   0.38923    0.6971    0.9540        GCLC        2729
## ENSG00000001167     398.8      -0.056003   0.09711  -0.57669    0.5641    0.9357        NFYA        4800
## ENSG00000001630     463.5       0.070002   0.09676   0.72348    0.4694    0.9123     CYP51A1        1595
## ENSG00000002822     169.5      -0.001926   0.13784  -0.01397    0.9889    0.9982      MAD1L1        8379
## ENSG00000003056     995.8       0.007716   0.06785   0.11373    0.9095    0.9859        M6PR        4074</code></pre>
<p>Using <strong>select</strong>, a function from <strong>AnnotationDbi</strong> for querying database objects, we get a table with the mapping from Entrez IDs to Reactome Path IDs :</p>
<pre class="r"><code>reactomeTable <- AnnotationDbi::select( reactome.db, 
   keys=as.character(res2$entrezid), keytype="ENTREZID", 
   columns=c("ENTREZID","REACTOMEID") )
head(reactomeTable)</code></pre>
<pre><code>##   ENTREZID REACTOMEID
## 1     8813     162699
## 2     8813     163125
## 3     8813     392499
## 4     8813     446193
## 5     8813     446203
## 6     8813     446219</code></pre>
<p>The next code chunk transforms this table into an <strong>incidence matrix</strong>. This is a Boolean matrix with one row for each Reactome Path and one column for each unique gene in <strong>res2</strong>, which tells us which genes are members of which Reactome Paths.</p>
<pre class="r"><code>#problem with this code is that res2$entrez are not unique
#ft2mat <- function(x, y) {
  # ux = unique(x)
  # uy = unique(y)
  # im = matrix(FALSE, nrow=length(ux), ncol=length(uy), dimnames=list(ux, uy))
  # im[ cbind(x, y) ] = TRUE
  # return(im)
 #}
#incm <- with(reactomeTable, ft2mat(REACTOMEID, ENTREZID))</code></pre>
<pre class="r"><code>incm <- do.call( rbind, with(reactomeTable, tapply( 
  ENTREZID, factor(REACTOMEID), function(x) res2$entrezid %in% x ) ))
colnames(incm) <- res2$entrez

str(incm)</code></pre>
<pre><code>##  logi [1:1458, 1:3400] FALSE FALSE FALSE FALSE FALSE FALSE ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : chr [1:1458] "1059683" "109581" "109582" "109606" ...
##   ..$ : chr [1:3400] "8813" "2729" "4800" "1595" ...</code></pre>
<p>We remove all rows corresponding to Reactome Paths with less than 20 or more than 80 assigned genes.</p>
<pre class="r"><code>within <- function(x, lower, upper) (x>=lower &amp; x<=upper)
incm <- incm[ within(rowSums(incm), lower=20, upper=80), ]</code></pre>
<p>To test whether the genes in a Reactome Path behave in a special way in our experiment, we calculate a number of statistics, including a <span class="math"><em>t</em></span>-statistic to see whether the average of the genes’ log2 fold change values in the gene set is different from zero. To facilitate the computations, we define a little helper function:</p>
<pre class="r"><code>testCategory <- function( reactomeID ) {
  isMember <- incm[ reactomeID, ]
  data.frame( 
     reactomeID  = reactomeID,
     numGenes    = sum( isMember ),
     avgLFC      = mean( res2$log2FoldChange[isMember] ),
     sdLFC       = sd( res2$log2FoldChange[isMember] ),
     zValue      = mean( res2$log2FoldChange[isMember] ) /sd( res2$log2FoldChange[isMember] ),
     strength    = sum( res2$log2FoldChange[isMember] ) / sqrt(sum(isMember)),
     pvalue      = t.test( res2$log2FoldChange[ isMember ] )$p.value,
     reactomeName = reactomePATHID2NAME[[reactomeID]],
     stringsAsFactors = FALSE ) }</code></pre>
<p>The function can be called with a Reactome Path ID:</p>
<pre class="r"><code>testCategory("109606")</code></pre>
<pre><code>##   reactomeID numGenes   avgLFC   sdLFC  zValue strength pvalue                                  reactomeName
## 1     109606       31 -0.02215 0.07769 -0.2852  -0.1234 0.1228 Homo sapiens: Intrinsic Pathway for Apoptosis</code></pre>
<p><span class="success"> As you can see the function not only performs the <span class="math"><em>t</em></span> test and returns the p value but also lists other useful information such as the number of genes in the category, the average log fold change, a “strength”" measure (see below) and the name with which Reactome describes the Path. </span></p>
<p>We call the function for all Paths in our incidence matrix and collect the results in a data frame:</p>
<pre class="r"><code>reactomeResult <- do.call( rbind, lapply( rownames(incm), testCategory ) )</code></pre>
<pre class="warning"><code>As we performed many tests, we should again use a multiple testing adjustment.</code></pre>
<pre class="r"><code>reactomeResult$padjust <- p.adjust( reactomeResult$pvalue, "BH" )</code></pre>
<p>This is a list of Reactome Paths which are significantly differentially expressed in our comparison of DPN treatment with control, sorted according to sign and strength of the signal:</p>
<pre class="r"><code>reactomeResultSignif <- reactomeResult[ reactomeResult$padjust < 0.05, ]
head( reactomeResultSignif[ order(-reactomeResultSignif$strength), ] )</code></pre>
<pre><code>##     reactomeID numGenes   avgLFC   sdLFC  zValue strength    pvalue
## 174     191273       21  0.10808 0.09894  1.0923   0.4953 6.786e-05
## 308     381070       41  0.07055 0.13898  0.5076   0.4517 2.341e-03
## 60     1638091       30  0.06877 0.10742  0.6402   0.3767 1.499e-03
## 150    1799339       75  0.04083 0.07791  0.5240   0.3536 2.153e-05
## 405      72689       64  0.02905 0.07284  0.3989   0.2324 2.213e-03
## 23     1169091       53 -0.02579 0.06195 -0.4162  -0.1877 3.804e-03
##                                                                  reactomeName  padjust
## 174                                    Homo sapiens: Cholesterol biosynthesis 0.007838
## 308                              Homo sapiens: IRE1alpha activates chaperones 0.041597
## 60                  Homo sapiens: Heparan sulfate/heparin (HS-GAG) metabolism 0.032968
## 150 Homo sapiens: SRP-dependent cotranslational protein targeting to membrane 0.003316
## 405                    Homo sapiens: Formation of a pool of free 40S subunits 0.041130
## 23                           Homo sapiens: Activation of NF-kappaB in B cells 0.048870</code></pre>
</div>
</div>
<div id="working-with-rlog-transformed-data" class="section level2">
<h2>Working with rlog-transformed data</h2>
<div id="the-rlog-transform" class="section level3">
<h3>The rlog transform</h3>
<p>Many common statistical methods for exploratory analysis of multidimensional data, especially methods for clustering (e.g., principal-component analysis and the like), work best for (at least approximately) homoskedastic data; this means that the variance of an observable quantity (i.e., here, the expression strength of a gene) does not depend on the mean. In RNA-Seq data, however, variance grows with the mean. For example, if one performs PCA directly on a matrix of normalized read counts, the result typically depends only on the few most strongly expressed genes because they show the largest absolute differences between samples. A simple and often used strategy to avoid this is to take the logarithm of the normalized count values plus a small pseudocount; however, now the genes with low counts tend to dominate the results because, due to the strong Poisson noise inherent to small count values, they show the strongest relative differences between samples.</p>
<p>As a solution, <strong>DESeq2</strong> offers the <strong>regularized-logarithm transformation</strong>, or <strong>rlog</strong> for short. For genes with high counts, the rlog transformation differs not much from an ordinary log2 transformation. For genes with lower counts, however, the values are shrunken towards the genes’ averages across all samples. Using an empirical Bayesian prior in the form of a <strong>ridge penalty</strong>, this is done such that the rlog-transformed data are approximately homoskedastic.</p>
<pre class="success"><code>Note that the rlog transformation is provided for applications other than differential testing. For differential testing we recommend the DESeq function applied to raw counts, as described earlier in this vignette, which also takes into account the dependence of the variance of counts on the mean value during the dispersion estimation step.</code></pre>
<p>The function <strong>rlog</strong> returns a <strong>SummarizedExperiment</strong> object which contains the rlog-transformed values in its <strong>assay</strong> slot:</p>
<pre class="r"><code>rld <- rlog( dds )
assay(rld)[ 1:3, 1:3]</code></pre>
<pre><code>##                 SRS308866 SRS308868 SRS308870
## ENSG00000000003    9.7614    9.7285    9.8653
## ENSG00000000005   -0.9813   -0.7408   -0.9447
## ENSG00000000419    8.0647    8.0770    8.1186</code></pre>
<p>To show the effect of the transformation, we plot the first sample against the second, first simply using the <strong>log2</strong> function (after adding 1, to avoid taking the log of zero), and then using the rlog-transformed values.</p>
<pre class="r"><code>plot( log2( 1+counts(dds, normalized=TRUE)[, 1:2] ), col="#00000020", pch=20, cex=0.3 )
plot( assay(rld)[, 1:2], col="#00000020", pch=20, cex=0.3 )</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_rldPlot1.png" title="plot of chunk beginner_rldPlot" alt="plot of chunk beginner_rldPlot" width="288" /><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_rldPlot2.png" title="plot of chunk beginner_rldPlot" alt="plot of chunk beginner_rldPlot" width="288" /></p>
<p>In Figure , we can see how genes with low counts seem to be excessively variable on the ordinary logarithmic scale, while the rlog transform compresses differences for genes for which the data cannot provide good information anyway.</p>
</div>
<div id="sample-distances" class="section level3">
<h3>Sample distances</h3>
<p>A useful first step in an RNA-Seq analysis is often to assess overall similarity between samples.</p>
<p>We use the R function <code>dist</code> to calculate the Euclidean distance between samples. To avoid that the distance measure is dominated by a few highly variable genes, and have a roughly equal contribution from all genes, we use it on the rlog-transformed data:</p>
<pre class="r"><code>sampleDists <- dist( t( assay(rld) ) )
as.matrix( sampleDists )[ 1:3, 1:3 ]</code></pre>
<pre><code>##           SRS308866 SRS308868 SRS308870
## SRS308866      0.00     32.87     31.21
## SRS308868     32.87      0.00     33.73
## SRS308870     31.21     33.73      0.00</code></pre>
<p><span class="success"> Note the use of the function <code>t</code> to transpose the data matrix. We need this because <code>dist</code> calculates distances between data <strong>rows</strong> and our samples constitute the columns. </span></p>
<p>We visualize the distances in a heatmap, using the function <code>heatmap.2</code> from the <strong>gplots</strong> package.</p>
<pre class="r"><code>sampleDistMatrix <- as.matrix( sampleDists )
rownames(sampleDistMatrix) <- paste( rld$treatment, 
   rld$patient, sep="-" )
colnames(sampleDistMatrix) <- NULL   
library( "gplots" )
library( "RColorBrewer" )
colours = colorRampPalette( rev(brewer.pal(9, "Blues")) )(255)
heatmap.2( sampleDistMatrix, trace="none", col=colours)</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_sampleDistHeatmap.png" title="plot of chunk beginner_sampleDistHeatmap" alt="plot of chunk beginner_sampleDistHeatmap" width="432" /></p>
<pre class="success"><code>Note that we have changed the row names of the distance matrix to contain treatment type and patient number instead of sample ID, so that we have all this information in view when looking at the heatmap. </code></pre>
<p>Another way to visualize sample-to-sample distances is a principal-components analysis (PCA). In this ordination method, the data points (i.e., here, the samples) are projected onto the 2D plane such that they spread out optimally.</p>
<pre class="r"><code>colours <- c(rgb(1:3/4,0,0),rgb(0,1:3/4,0),rgb(0,0,1:3/4),rgb(1:3/4,0,1:3/4))
plotPCA( rld, intgroup = c("patient","treatment"), col=colours )</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_samplePCA.png" title="plot of chunk beginner_samplePCA" alt="plot of chunk beginner_samplePCA" width="432" /></p>
<p><span class="warning"> Here, we have used the function <code>plotPCA</code> which comes with <strong>DESeq2</strong>. The two terms specified as <code>intgroup</code> are column names from our sample data; they tell the function to use them to choose colours. </span></p>
<p>From both visualizations, we see that the differences between patients is much larger than the difference between treatment and control samples of the same patient. This shows why it was important to account for this paired design (``paired’’, because each treated sample is paired with one control sample from the <strong>same</strong> patient).</p>
<p>We did so by using the design formula <code>~ patient + treatment</code> when setting up the data object in the beginning. Had we used an un-paired analysis, by specifying only , we would not have found many hits, because then, the patient-to-patient differences would have drowned out any treatment effects.</p>
</div>
<div id="gene-clustering" class="section level3">
<h3>Gene clustering</h3>
<p>In the above heatmap, the dendrogram at the side shows us a hierarchical clustering of the samples. Such a clustering can also be performed for the genes.</p>
<p>Since the clustering is only relevant for genes that actually carry signal, one usually carries it out only for a subset of most highly variable genes. Here, for demonstration, let us select the 35 genes with the highest variance across samples:</p>
<pre class="r"><code>library( "genefilter" )
topVarGenes <- head( order( rowVars( assay(rld) ), decreasing=TRUE ), 35 )</code></pre>
<p>The heatmap becomes more interesting if we do not look at absolute expression strength but rather at the amount by which each gene deviates in a specific sample from the gene’s average across all samples. Hence, we center and scale each genes’ values across samples, and plot a heatmap.</p>
<pre class="r"><code>heatmap.2( assay(rld)[ topVarGenes, ], scale="row", 
     trace="none", dendrogram="column", 
     col = colorRampPalette( rev(brewer.pal(9, "RdBu")) )(255),
     ColSideColors = c( Control="gray", DPN="darkgreen", OHT="orange" )[
        colData(rld)$treatment ] )</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-seq-differential-expression-workflow-using-deseq2-beginner_geneHeatmap.png" title="plot of chunk beginner_geneHeatmap" alt="plot of chunk beginner_geneHeatmap" width="672" /></p>
<pre class="warning"><code>We can now see on the heatmap, blocks of genes which covary across patients. Often, such a heatmap is insightful, even though here, seeing these variations across patients is of limited value because we are rather interested in the effects between the treatments from each patient. </code></pre>
</div>
<div id="going-further" class="section level3">
<h3>Going further</h3>
<p>Analyze more datasets: use the function defined in the following code chunk to download a processed count matrix from the <a href="http://bowtie-bio.sourceforge.net/recount/">ReCount website</a>.</p>
<p>The following function takes a name of the dataset from the ReCount website, e.g. <strong>“hammer”</strong>, and returns a <strong>SummarizedExperiment</strong> object.</p>
<pre class="r"><code>recount2SE <- function(name) {
  filename <- paste0(name,"_eset.RData")
  if (!file.exists(filename)) download.file(paste0(
    "http://bowtie-bio.sourceforge.net/recount/ExpressionSets/",
    filename),filename)
  load(filename)
  e <- get(paste0(name,".eset"))
  se <- SummarizedExperiment(SimpleList(counts=exprs(e)),
                             colData=DataFrame(pData(e)))
  se                   
}</code></pre>
</div>
</div>
<div id="see-also" class="section level2">
<h2>See also</h2>
<p>For a more in-depth explanation of the advanced details, we advise you to proceed to the vignette of the DESeq2 package package, Differential analysis of count data. For a treatment of exon-level differential expression, we refer to the vignette of the DEXSeq package, Analyzing RN-seq data for differential exon usage with the DEXSeq package.</p>
<p><code>DEXSeq</code> for differential exon usage. See the accompanying vignette, <strong>Analyzing RNA-seq data for differential exon usage with the DEXSeq package</strong>, which is similar to the style of this tutorial.</p>
<ul>
<li>Other Bioconductor packages for RNA-Seq differential expression:</li>
</ul>
<p><strong>edgeR</strong>, <strong>limma</strong>, <strong>DSS</strong>, <strong>BitSeq</strong> (transcript level), <strong>EBSeq</strong>, <strong>cummeRbund</strong> (for importing and visualizing Cufflinks results), <strong>monocle</strong> (single-cell analysis). More at <a href="http://bioconductor.org/packages/release/BiocViews.html#___RNASeq">http://bioconductor.org/packages/release/BiocViews.html#___RNASeq</a></p>
<ul>
<li>Methods for gene set testing: <strong>romer</strong> and <strong>roast</strong> in <strong>limma</strong>, permutation based: <strong>safe</strong>
</li>
<li>Packages for normalizing for covariates (e.g., GC content): <strong>cqn</strong>, <strong>EDASeq</strong>
</li>
<li>Packages for detecting batches: <strong>sva</strong>, <strong>RUVSeq</strong>
</li>
<li>Generating HTML results tables with links to outside resources (gene descriptions): <strong>ReportingTools</strong></li>
</ul>
</div>
<div id="session-info" class="section level2">
<h2>Session Info</h2>
<p>As last part of this document, we call the function , which reports the version numbers of R and all the packages used in this session. It is good practice to always keep such a record as it will help to trace down what has happened in case that an R script ceases to work because a package has been changed in a newer version.</p>
<p>R version 3.1.0 (2014-04-10) Platform: x86_64-apple-darwin13.1.0 (64-bit)</p>
<p>locale: [1] fr_FR.UTF-8/fr_FR.UTF-8/fr_FR.UTF-8/C/fr_FR.UTF-8/fr_FR.UTF-8</p>
<p>attached base packages: [1] parallel stats graphics grDevices utils datasets methods base</p>
<p>other attached packages: [1] genefilter_1.46.1 RColorBrewer_1.0-5 gplots_2.14.2 reactome.db_1.48.0
 [5] org.Hs.eg.db_2.14.0 RSQLite_0.11.4 DBI_0.3.1 DESeq2_1.4.5
 [9] RcppArmadillo_0.4.450.1.0 Rcpp_0.11.3 GenomicAlignments_1.0.6 BSgenome_1.32.0
[13] GenomicFeatures_1.16.2 AnnotationDbi_1.26.0 Biobase_2.24.0 Rsamtools_1.16.1
[17] Biostrings_2.32.1 XVector_0.4.0 parathyroidSE_1.2.0 GenomicRanges_1.16.4
[21] GenomeInfoDb_1.0.2 IRanges_1.22.10 BiocGenerics_0.10.0</p>
<p>loaded via a namespace (and not attached): [1] annotate_1.42.1 base64enc_0.1-2 BatchJobs_1.4 BBmisc_1.7 BiocParallel_0.6.1 biomaRt_2.20.0
 [7] bitops_1.0-6 brew_1.0-6 caTools_1.17.1 checkmate_1.4 codetools_0.2-9 digest_0.6.4
[13] evaluate_0.5.5 fail_1.2 foreach_1.4.2 formatR_1.0 gdata_2.13.3 geneplotter_1.42.0 [19] grid_3.1.0 gtools_3.4.1 htmltools_0.2.6 iterators_1.0.7 KernSmooth_2.23-13 knitr_1.6
[25] lattice_0.20-29 locfit_1.5-9.1 RCurl_1.95-4.3 rmarkdown_0.3.3 rtracklayer_1.24.2 sendmailR_1.2-1
[31] splines_3.1.0 stats4_3.1.0 stringr_0.6.2 survival_2.37-7 tools_3.1.0 XML_3.98-1.1
[37] xtable_1.7-4 yaml_2.1.13 zlibbioc_1.10.0</p>
<hr />
<p><strong>References</strong></p>
<ul>
<li>Michael Love, Simon Anders, Wolfgang Huber, RNA-Seq differential expression workfow : <a href="http://www.bioconductor.org/help/course-materials/2014/BioC2014/RNA-Seq-Analysis-Lab.pdf">http://www.bioconductor.org/help/course-materials/2014/BioC2014/RNA-Seq-Analysis-Lab.pdf</a>
</li>
<li>Courses: <a href="http://www.bioconductor.org/help/course-materials/2014/CSAMA2014/">http://www.bioconductor.org/help/course-materials/2014/CSAMA2014/</a></li>
</ul>
</div>

<script>jQuery(document).ready(function () {jQuery('h1,h2,h3,h4').addClass('formatter-title');});//add phpboost class to header</script>
<style>.content{padding:0px;}</style>
</div><!--end rdoc-->
<!--====================== stop here when you copy to sthda================-->


<!-- END HTML -->]]></description>
			<pubDate>Tue, 14 Oct 2014 00:13:54 +0200</pubDate>
			
		</item>
		
		<item>
			<title><![CDATA[RNA sequencing data analysis - Counting, normalization and differential expression]]></title>
			<link>https://www.sthda.com/english/wiki/rna-sequencing-data-analysis-counting-normalization-and-differential-expression</link>
			<guid>https://www.sthda.com/english/wiki/rna-sequencing-data-analysis-counting-normalization-and-differential-expression</guid>
			<description><![CDATA[<!-- START HTML -->

            
  <!--====================== start from here when you copy to sthda================-->  
  <div id="rdoc">


<div id="TOC">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#counting-reads-in-genes">Counting reads in genes</a></li>
<li><a href="#load-data">Load data</a></li>
<li><a href="#normalization">Normalization</a><ul>
<li><a href="#why-rnaseq-data-should-be-normalized">Why RNAseq data should be normalized ?</a></li>
<li><a href="#normalization-using-deseq2-size-factors">Normalization using DESeq2 (size factors)</a></li>
</ul></li>
<li><a href="#exploratory-data-analysis">Exploratory data analysis</a></li>
<li><a href="#normalization-to-stabilize-variance-regularized-logarithm">Normalization to stabilize variance (regularized logarithm)</a></li>
<li><a href="#differential-gene-expression">Differential gene expression</a></li>
<li><a href="#footnotes">Footnotes <a name="foot"></a></a><ul>
<li><a href="#introduction-1">Introduction</a></li>
<li><a href="#hammer-et-al">Hammer et al</a></li>
<li><a href="#recount">ReCount</a></li>
<li><a href="#negative-binomial-methods-for-differential-expression-of-count-data">Negative Binomial methods for differential expression of count data</a></li>
<li><a href="#transformation-followed-by-linear-model-methods">Transformation followed by linear model methods</a></li>
<li><a href="#resampling-based-methods">Resampling-based methods</a></li>
<li><a href="#incorporating-isoform-abundance">Incorporating isoform-abundance</a></li>
</ul></li>
<li><a href="#licence">Licence</a></li>
<li><a href="#references">References</a></li>
</ul>
</div>

<hr />
<p><span class="warning"> This analysis was performed using R (ver. 3.1.0). </span></p>
<div id="introduction" class="section level2">
<h2>Introduction</h2>
<p>RNA-Seq is a valuable experiment for quantifying both the types and the amount of RNA molecules in a sample.</p>
<p>In this article, we will focus on comparing the expression levels of different samples, by counting the number of reads which overlap the exons of genes defined by a known annotation.</p>
</div>
<div id="counting-reads-in-genes" class="section level2">
<h2>Counting reads in genes</h2>
<p>We will work with a count matrix, which has genes along the rows and samples along the columns. The elements in the matrix give the number of reads which could be uniquely aligned to a given gene for a given sample.</p>
</div>
<div id="load-data" class="section level2">
<h2>Load data</h2>
<p>We will work with the <a href="#foot">Hammer et al</a> dataset, as prepared by the <a href="http://bowtie-bio.sourceforge.net/recount/">ReCount website</a></p>
<blockquote>
<p>ReCount is an online resource consisting of RNA-seq gene count datasets built using the raw data from 18 different studies. The raw sequencing data (.fastq files) were processed with Myrna to obtain tables of counts for each gene.</p>
</blockquote>
<p><span class="warning"> This is really helpful for us, so we don’t have to download all the FASTQ files and map them ourselves. If you use this resource, you should cite <a href="#foot">Frazee (2011)</a>, and cite the appropriate paper for the experimental data that you download. </span></p>
<p>Here we read in the <code>Eset</code> hosted by ReCount, and turn it into a <strong>SummarizedExperiment</strong>. The matrix is an expression set.</p>
<pre class="r"><code>#download data
link <- "http://bowtie-bio.sourceforge.net/recount/ExpressionSets/hammer_eset.RData"
if (!file.exists("hammer_eset.RData")) download.file(link, "hammer_eset.RData")
#Load the matrix
load("hammer_eset.RData")
library(Biobase)
library(GenomicRanges)
# the SimpleList() part below is only necessary for Bioc <= 2.13
#se <- SummarizedExperiment(SimpleList(counts=exprs(hammer.eset)))
se <- SummarizedExperiment(exprs(hammer.eset))
colData(se) <- DataFrame(pData(hammer.eset))</code></pre>
<p><strong>Column data contains some informations about sample caracteristics.</strong> We have the eight samples (4 controls and four of which had spinal nerve ligation). There’s sequencing after two months after spinal nerve ligation and sequencing after two weeks of spinal nerve ligation.</p>
<pre class="r"><code>#column data
colData(se)</code></pre>
<pre><code>## DataFrame with 8 rows and 5 columns
##                   sample.id num.tech.reps protocol         strain     Time
##                    <factor>     <numeric> <factor>       <factor> <factor>
## SRX020102         SRX020102             1  control Sprague Dawley 2 months
## SRX020103         SRX020103             2  control Sprague Dawley 2 months
## SRX020104         SRX020104             1   L5 SNL Sprague Dawley 2 months
## SRX020105         SRX020105             2   L5 SNL Sprague Dawley  2months
## SRX020091-3     SRX020091-3             1  control Sprague Dawley  2 weeks
## SRX020088-90   SRX020088-90             2  control Sprague Dawley  2 weeks
## SRX020094-7     SRX020094-7             1   L5 SNL Sprague Dawley  2 weeks
## SRX020098-101 SRX020098-101             2   L5 SNL Sprague Dawley  2 weeks</code></pre>
<pre class="r"><code>#We need to fix a typo in the Time column:
colData(se)$Time[4] <- "2 months"
colData(se)$Time <- factor(colData(se)$Time)
colData(se)$Time</code></pre>
<pre><code>## [1] 2 months 2 months 2 months 2 months 2 weeks  2 weeks  2 weeks  2 weeks 
## Levels: 2 months 2 weeks</code></pre>
</div>
<div id="normalization" class="section level2">
<h2>Normalization</h2>
<div id="why-rnaseq-data-should-be-normalized" class="section level3">
<h3>Why RNAseq data should be normalized ?</h3>
<p>The counts of the summarized experiment are in the assay slot.</p>
<pre class="r"><code>#The count of experiment
head(assay(se))</code></pre>
<pre><code>##                    SRX020102 SRX020103 SRX020104 SRX020105 SRX020091-3 SRX020088-90 SRX020094-7 SRX020098-101
## ENSRNOG00000000001         2         4        18        24           7            4          93            77
## ENSRNOG00000000007         4         1         3         1           5            4           9             4
## ENSRNOG00000000008         0         1         4         2           0            5           2             6
## ENSRNOG00000000009         0         0         0         0           0            0           0             0
## ENSRNOG00000000010        19        10        19        13          50           57          45            58
## ENSRNOG00000000012         7         5         1         0          31           26          12             9</code></pre>
<pre class="r"><code>#column sums of the count
colSums(assay(se))</code></pre>
<pre><code>##     SRX020102     SRX020103     SRX020104     SRX020105   SRX020091-3  SRX020088-90   SRX020094-7 SRX020098-101 
##       5282855       4562100       4897807       5123782      17705411      17449646      23649094      23537179</code></pre>
<p><span class="warning"> If you look at the column sums of the counts, you can see that each sample had a different amount of reads which could be aligned to the different genes. So if we’re going to do some analysis, we definitely need to take care of the fact that the different samples had different sequencing depth. </span></p>
<p>It’s not a great idea to use the number of reads which map to genes as a normalizing factor. There have been a number of papers showing that, this number is susceptible to being altered by a single gene. You might have one or a dozen genes which have very high gene expression, and those genes play the largest role in determining this sum. There are a number of more robust estimators. Probably using any of those robust estimators is better than using this sum.</p>
<p><span class="success"> We’re going to use the median ratio method, which is in the DESeq2 package. </span></p>
</div>
<div id="normalization-using-deseq2-size-factors" class="section level3">
<h3>Normalization using DESeq2 (size factors)</h3>
<p>We will use the <code>DESeq2</code> package to normalize the sample for sequencing depth. For now, don’t worry about the <code>design</code> argument.</p>
<p>In order to use this normalization method, we have to build a <strong>DESeqDataSet</strong>, which just a summarized experiment with something called a design (a formula which specifies the design of the experiment). So we’ll explain this in the next unit, but we just need to specify something. So I’m going to specify tilde 1.</p>
<pre class="r"><code># biocLite("DESeq2")
library(DESeq2)
dds <- DESeqDataSet( se, design = ~ 1 )
#names(assays(dds))</code></pre>
<p>The following code estimates <strong>size factors</strong> to account for differences in sequencing depth. So the value are typically centered around 1. If all the samples have exactly the same sequencing depth, you expect these numbers to be near 1. But instead, we see that the first sample and the 7th sample have about a difference of more than 4.</p>
<pre class="r"><code>#Estimate size factors
dds <- estimateSizeFactors( dds )
sizeFactors(dds)</code></pre>
<pre><code>##     SRX020102     SRX020103     SRX020104     SRX020105   SRX020091-3  SRX020088-90   SRX020094-7 SRX020098-101 
##        0.5211        0.4479        0.5122        0.5323        1.6893        1.6874        2.4138        2.3777</code></pre>
<pre class="r"><code>colSums(counts(dds))</code></pre>
<pre><code>##     SRX020102     SRX020103     SRX020104     SRX020105   SRX020091-3  SRX020088-90   SRX020094-7 SRX020098-101 
##       5282855       4562100       4897807       5123782      17705411      17449646      23649094      23537179</code></pre>
<pre class="r"><code>#Plot column sums according to size factor
plot(sizeFactors(dds), colSums(counts(dds)))
abline(lm(colSums(counts(dds)) ~ sizeFactors(dds) + 0))</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-size-factors.png" title="plot of chunk size-factors" alt="plot of chunk size-factors" width="288" /></p>
<p><span class="success"> Now we can divide the columns by the size factor and take the log2 of these normalized counts plus a pseudocount of 1. We transpose in order to run PCA. </span></p>
<pre class="r"><code>#The argument normalized equals true, divides each column by its size factor.
logcounts <- log2( counts(dds, normalized=TRUE) + 1 )
pc <- prcomp( t( logcounts ) )</code></pre>
</div>
</div>
<div id="exploratory-data-analysis" class="section level2">
<h2>Exploratory data analysis</h2>
<p>You can see that the samples are basically clustering by the first principal component, which is in this case the protocol. More variance explained by protocol than by time. You could also do a hierarchical clustering, and you could see that here again, they’re separated more by protocol than by time. You can see they don’t actually cluster discreetly by time.</p>
<pre class="r"><code>#library(devtools)
#install_github("rafalib", "ririzarr")
library(rafalib)
#PC 1 VS PC 2
plot(pc$x[,1], pc$x[,2], 
     col=colData(dds)$protocol, # color is the protocol
     pch=as.numeric(colData(dds)$Time)+15)# point shape by time
#hierarchical clustering
plot(hclust(dist(t(logcounts))), labels=colData(dds)$protocol)
plot(hclust(dist(t(logcounts))), labels=colData(dds)$Time)</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-exploratory-data-analysis1.png" title="plot of chunk exploratory-data-analysis" alt="plot of chunk exploratory-data-analysis" width="288" /><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-exploratory-data-analysis2.png" title="plot of chunk exploratory-data-analysis" alt="plot of chunk exploratory-data-analysis" width="288" /><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-exploratory-data-analysis3.png" title="plot of chunk exploratory-data-analysis" alt="plot of chunk exploratory-data-analysis" width="288" /></p>
<p>And finally, we can just take a look at the log accounts of the first two samples against each other. What I’m trying to point out here is, as we saw in an earlier unit, you can see there’s a spread of the points. So there’s extra variance in the log space when you get down to low values, which is sometimes called Poisson noise.</p>
<pre class="r"><code>#log count of the first two samples
plot(logcounts[,1], logcounts[,2], cex=.1)</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-logcount.png" title="plot of chunk logcount" alt="plot of chunk logcount" width="288" /></p>
<p><span class="warning"> Now we will use a normalization method, which is similar to the variance stablizing normalization method mentioned. It uses the variance model to shrink together the sample values for lowly expressed genes with high variance. </span></p>
</div>
<div id="normalization-to-stabilize-variance-regularized-logarithm" class="section level2">
<h2>Normalization to stabilize variance (regularized logarithm)</h2>
<p>The data is in the <code>assay</code> slot, and needs to be transposed as before to run PCA.</p>
<pre class="r"><code># this takes ~15 seconds
# normalization to stabilize variance (regularized logarithm)
rld <- rlog( dds ) # object of class GenomicRanges 
# if using Bioc 2.13:
# rld <- rlogTransformation( dds )</code></pre>
<p>We see again, the protocol drives the variance. But if you look at the time dimension, now the times cluster together discreetly. So instead of before, we had two months joining with the two weeks, now they join each other first, and then they join as a protocol. We could look at the plot of the first sample against the second sample. We can see what, the values near 0 were shrunk towards each other.</p>
<p>We can look at the same plots now using this transformed data:</p>
<pre class="r"><code>pc2 <- prcomp( t( assay(rld) ) )
plot(pc2$x[,1], pc2$x[,2],  col=colData(rld)$protocol,pch=as.numeric(colData(rld)$Time)+15)
plot(hclust(dist(t(assay(rld)))), labels=colData(rld)$protocol)
plot(hclust(dist(t(assay(rld)))), labels=colData(rld)$Time)
plot(assay(rld)[,1], assay(rld)[,2], cex=.1)</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-variance-stabilization1.png" title="plot of chunk variance-stabilization" alt="plot of chunk variance-stabilization" width="288" /><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-variance-stabilization2.png" title="plot of chunk variance-stabilization" alt="plot of chunk variance-stabilization" width="288" /><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-variance-stabilization3.png" title="plot of chunk variance-stabilization" alt="plot of chunk variance-stabilization" width="288" /><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-variance-stabilization4.png" title="plot of chunk variance-stabilization" alt="plot of chunk variance-stabilization" width="288" /></p>
</div>
<div id="differential-gene-expression" class="section level2">
<h2>Differential gene expression</h2>
<p>A number of methods for assessing differential gene expression from RNA-Seq counts use the Negative Binomial distribution to make probabilistic statements about the differences seen in an experiment. A few such methods are <a href="#foot">edgeR</a>, <a href="#foot">DESeq</a>, <a href="#foot">DSS</a> and <em>many</em> others. A very incomplete list of other methods is provided in the <a href="#foot">footnotes</a>.</p>
<p><span class="success"> We will use <code>DESeq2</code> to perform differential gene expression on the counts. This also uses a Negative Binomial distribution to model the counts. It performs a similar step to <code>limma</code>, in using the variance of all the genes to improve the variance estimate for each individual gene. In addition, it shrinks the high variance fold changes, which will be seen in the resulting MA-plot. </span></p>
<p>Before we specified a design for this, which was just tilde 1. And that represented just modeling these counts on an intercept value. But for differential expression analysis, we want to model them based on the design of the experiment. The design of the experiment was two different treatments, spinal nerve ligation and control, and sequencing was done at two different times.</p>
<p>First, we setup the <code>design</code> of the experiment, so that differences will be considered across time and protocol variables. The last variable is used for the default results tables and plots, and we make sure the “control” level is the first level, such that log fold changes will be treatment over control, and not control over treatment.</p>
<p>If control was not the base level, because the factoring is done alphabetically, you could use the relevel function in R, and give it the level that you want to be the first. So this would just then set control as the first level, if it wasn’t already so.</p>
<pre class="r"><code>colData(dds)$protocol</code></pre>
<pre><code>## [1] control control L5 SNL  L5 SNL  control control L5 SNL  L5 SNL 
## Levels: control L5 SNL</code></pre>
<pre class="r"><code># if control was not already the "base level", we would do:
# set control as the first level, if it wasn&amp;#39;t already so.
colData(dds)$protocol <- relevel(colData(dds)$protocol, "control")
levels(colData(dds)$protocol)</code></pre>
<pre><code>## [1] "control" "L5 SNL"</code></pre>
<pre class="r"><code>#Change the design
design(dds) <- ~ Time + protocol</code></pre>
<p><span class="warning"> We put the protocol as the last variable of the design, because this is the variable that will be used to generate log fold changes. So we want to know, controlling for time, what genes were changed according to the protocol. </span></p>
<p>The following line runs the model, and then we can extract a results table for all genes:</p>
<pre class="r"><code># this takes ~20 seconds
dds <- DESeq( dds )
res <- results( dds )
head(res)</code></pre>
<pre><code>## log2 fold change (MAP): protocol L5 SNL vs control 
## Wald test p-value: protocol L5 SNL vs control 
## DataFrame with 6 rows and 6 columns
##                     baseMean log2FoldChange     lfcSE      stat    pvalue      padj
##                    <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSRNOG00000000001    21.304         2.9267    0.4055    7.2180 5.275e-13 4.219e-12
## ENSRNOG00000000007     3.548        -0.1309    0.6373   -0.2054 8.373e-01 8.886e-01
## ENSRNOG00000000008     2.514         0.7699    0.7314    1.0526 2.925e-01 4.039e-01
## ENSRNOG00000000009     0.000             NA        NA        NA        NA        NA
## ENSRNOG00000000010    28.340        -0.3193    0.2899   -1.1013 2.708e-01 3.798e-01
## ENSRNOG00000000012     8.633        -1.9587    0.4943   -3.9628 7.409e-05 2.411e-04</code></pre>
<p><strong>baseMean</strong> is the average mean expression
<strong>stat</strong> = log2FoldChange/ lfcSE</p>
<p>We can also make other results tables, such as control over SNL, or for comparing the time variable.</p>
<pre class="r"><code>#switch the numerator and the denominator
#For the protocol variable I want the control over L5 SNL
head(results(dds, contrast=c("protocol","control","L5 SNL")))</code></pre>
<pre><code>## log2 fold change (MAP): protocol control vs L5 SNL 
## Wald test p-value: protocol control vs L5 SNL 
## DataFrame with 6 rows and 6 columns
##                     baseMean log2FoldChange     lfcSE      stat    pvalue      padj
##                    <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSRNOG00000000001    21.304        -2.9267    0.4055   -7.2180 5.275e-13 4.219e-12
## ENSRNOG00000000007     3.548         0.1309    0.6373    0.2054 8.373e-01 8.886e-01
## ENSRNOG00000000008     2.514        -0.7699    0.7314   -1.0526 2.925e-01 4.039e-01
## ENSRNOG00000000009     0.000             NA        NA        NA        NA        NA
## ENSRNOG00000000010    28.340         0.3193    0.2899    1.1013 2.708e-01 3.798e-01
## ENSRNOG00000000012     8.633         1.9587    0.4943    3.9628 7.409e-05 2.411e-04</code></pre>
<pre class="r"><code>#You can also build result for time variable
head(results(dds, contrast=c("Time","2 months","2 weeks")))</code></pre>
<pre><code>## log2 fold change (MAP): Time 2 months vs 2 weeks 
## Wald test p-value: Time 2 months vs 2 weeks 
## DataFrame with 6 rows and 6 columns
##                     baseMean log2FoldChange     lfcSE      stat    pvalue      padj
##                    <numeric>      <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSRNOG00000000001    21.304         0.2950    0.3227    0.9143    0.3605    0.5496
## ENSRNOG00000000007     3.548         0.3728    0.4307    0.8656    0.3867        NA
## ENSRNOG00000000008     2.514         0.3814    0.4162    0.9163    0.3595        NA
## ENSRNOG00000000009     0.000             NA        NA        NA        NA        NA
## ENSRNOG00000000010    28.340         0.1863    0.2753    0.6766    0.4986    0.6726
## ENSRNOG00000000012     8.633        -0.5253    0.4018   -1.3073    0.1911        NA</code></pre>
<p>We can now contruct an MA-plot of the fold change over the average expression level of all samples.</p>
<pre class="r"><code># Bioc 2.13
plotMA(dds, ylim=c(-5,5))
# Bioc 2.14
plotMA(res, ylim=c(-5,5))</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-plotma.png" title="plot of chunk plotma" alt="plot of chunk plotma" width="288" /></p>
<p>And you can see, highlighted in red, are those genes which had an adjusted p-value less than 0.1.</p>
<p>Suppose we are not interested in small log2 fold changes even if they are significantly differentially expressed. We can also test for log2 fold changes larger than 1 in absolute value.</p>
<p>So there’s a way to specify this to the results function, to say I’m only interested in genes which have a log 2 fold change greater in absolute value than 1. And this is not just filtering based on the fold change, but it’s actually performing a statistical test.</p>
<pre class="r"><code>resBigFC <- results(dds, lfcThreshold=1, altHypothesis="greaterAbs")
plotMA(resBigFC, ylim=c(-5,5))
abline(h=c(-1,1),lwd=5)</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-plotMA2.png" title="plot of chunk plotMA2" alt="plot of chunk plotMA2" width="288" /></p>
<p>Let’s examine the top gene, sorting by p-value:</p>
<pre class="r"><code>#Top genes : sort by pvalue
resSort <- res[order(res$pvalue),]
head(resSort)</code></pre>
<pre><code>## log2 fold change (MAP): protocol L5 SNL vs control 
## Wald test p-value: protocol L5 SNL vs control 
## DataFrame with 6 rows and 6 columns
##                     baseMean log2FoldChange     lfcSE      stat     pvalue       padj
##                    <numeric>      <numeric> <numeric> <numeric>  <numeric>  <numeric>
## ENSRNOG00000004805    1127.9          4.068   0.10665     38.15  0.000e+00  0.000e+00
## ENSRNOG00000004874    1271.5          2.498   0.08466     29.50 2.532e-191 2.016e-187
## ENSRNOG00000015156    1166.1          3.383   0.12076     28.01 1.090e-172 5.784e-169
## ENSRNOG00000004731     892.4         -2.588   0.09352    -27.67 1.620e-168 6.450e-165
## ENSRNOG00000003745    2495.9          3.196   0.12372     25.83 3.707e-147 1.181e-143
## ENSRNOG00000032884    3219.1         -2.466   0.09607    -25.66 2.889e-145 7.669e-142</code></pre>
<pre class="r"><code>#Count for the first gene: the unnormalized count
k <- counts(dds)[rownames(resSort)[1],]

#Make a stripchart by combining time and protocol
cond <- with(colData(se), factor(paste(Time, protocol)))
stripchart(log2(k + 1) ~ cond, method="jitter", vertical=TRUE, las=2)</code></pre>
<p><img src="https://www.sthda.com/english/sthda/RDoc/figure/genomics/rna-sequencing-data-analysis-counting-normalization-and-differential-expression-topgenes.png" title="plot of chunk topgenes" alt="plot of chunk topgenes" width="288" /></p>
<p>You can see why this was given such a low p-value is because if you look at this change from control to spinal nerve ligation, it’s a very large log2 fold change. And it’s consistent, also, across time. And that leads to this very low p-value.</p>
<p>We can then check the annotation of these highly significant genes:</p>
<pre class="r"><code># biocLite("org.Rn.eg.db")
library(org.Rn.eg.db)
#The keys we can query on Ensembl
keytypes(org.Rn.eg.db)</code></pre>
<pre><code>##  [1] "ENTREZID"     "PFAM"         "IPI"          "PROSITE"      "ACCNUM"       "ALIAS"        "CHR"         
##  [8] "CHRLOC"       "CHRLOCEND"    "ENZYME"       "PATH"         "PMID"         "REFSEQ"       "SYMBOL"      
## [15] "UNIGENE"      "ENSEMBL"      "ENSEMBLPROT"  "ENSEMBLTRANS" "GENENAME"     "UNIPROT"      "GO"          
## [22] "EVIDENCE"     "ONTOLOGY"     "GOALL"        "EVIDENCEALL"  "ONTOLOGYALL"</code></pre>
<pre class="r"><code>head(rownames(dds))</code></pre>
<pre><code>## [1] "ENSRNOG00000000001" "ENSRNOG00000000007" "ENSRNOG00000000008" "ENSRNOG00000000009" "ENSRNOG00000000010"
## [6] "ENSRNOG00000000012"</code></pre>
<pre class="r"><code>#The first 20 genes according to the lowest p-value
geneinfo <- select(org.Rn.eg.db, keys=rownames(resSort)[1:20],
                   columns=c("ENSEMBL","SYMBOL","GENENAME"), 
                   keytype="ENSEMBL")
geneinfo</code></pre>
<pre><code>##               ENSEMBL     SYMBOL                                                           GENENAME
## 1  ENSRNOG00000004805      Stac2                                     SH3 and cysteine rich domain 2
## 2  ENSRNOG00000004874      Flrt3                   fibronectin leucine rich transmembrane protein 3
## 3  ENSRNOG00000015156        Gal                                         galanin/GMAP prepropeptide
## 4  ENSRNOG00000004731       Ano3                                                        anoctamin 3
## 5  ENSRNOG00000003745       Atf3                                  activating transcription factor 3
## 6  ENSRNOG00000032884     Scn11a              sodium channel, voltage-gated, type XI, alpha subunit
## 7  ENSRNOG00000018808        Vip                                      vasoactive intestinal peptide
## 8  ENSRNOG00000033531   Cacna2d1         calcium channel, voltage-dependent, alpha2/delta subunit 1
## 9  ENSRNOG00000032473     Scn10a               sodium channel, voltage-gated, type X, alpha subunit
## 10 ENSRNOG00000019486      Trpv1 transient receptor potential cation channel, subfamily V, member 1
## 11 ENSRNOG00000009186      Stmn4                                                    stathmin-like 4
## 12 ENSRNOG00000012448     Chrnb3                 cholinergic receptor, nicotinic, beta 3 (neuronal)
## 13 ENSRNOG00000019574     Cuedc2                                            CUE domain containing 2
## 14 ENSRNOG00000031997       <NA>                                                               <NA>
## 15 ENSRNOG00000002595      Dpp10                                             dipeptidylpeptidase 10
## 16 ENSRNOG00000027331      Ppef1              protein phosphatase, EF-hand calcium binding domain 1
## 17 ENSRNOG00000015055       Scg2                                                   secretogranin II
## 18 ENSRNOG00000000129 RGD1559864                                       similar to mKIAA1045 protein
## 19 ENSRNOG00000003386     Rbfox3                  RNA binding protein, fox-1 homolog (C. elegans) 3
## 20 ENSRNOG00000020136       Tgm1                                                 transglutaminase 1</code></pre>
</div>
<div id="footnotes" class="section level2">
<h2>Footnotes <a name="foot"></a></h2>
<div id="introduction-1" class="section level3">
<h3>Introduction</h3>
<p>Mortazavi A, Williams BA, McCue K, Schaeffer L, Wold B., “Mapping and quantifying mammalian transcriptomes by RNA-Seq”, Nat Methods. 2008. <a href="http://www.nature.com/nmeth/journal/v5/n7/full/nmeth.1226.html">http://www.nature.com/nmeth/journal/v5/n7/full/nmeth.1226.html</a></p>
<p>John C. Marioni, Christopher E. Mason, Shrikant M. Mane, Matthew Stephens, and Yoav Gilad, “RNA-seq: An assessment of technical reproducibility and comparison with gene expression arrays” Genome Res. 2008. <a href="http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2527709/">http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2527709/</a></p>
</div>
<div id="hammer-et-al" class="section level3">
<h3>Hammer et al</h3>
<p>Hammer P, Banck MS, Amberg R, Wang C, Petznick G, Luo S, Khrebtukova I, Schroth GP, Beyerlein P, Beutler AS. “mRNA-seq with agnostic splice site discovery for nervous system transcriptomics tested in chronic pain.” Genome Res. 2010 <a href="http://www.ncbi.nlm.nih.gov/pubmed?term=20452967">http://www.ncbi.nlm.nih.gov/pubmed?term=20452967</a></p>
</div>
<div id="recount" class="section level3">
<h3>ReCount</h3>
<p>Frazee AC, Langmead B, Leek JT. “ReCount: a multi-experiment resource of analysis-ready RNA-seq gene count datasets”. BMC Bioinformatics 12:449 <a href="http://www.ncbi.nlm.nih.gov/pubmed/22087737">http://www.ncbi.nlm.nih.gov/pubmed/22087737</a></p>
</div>
<div id="negative-binomial-methods-for-differential-expression-of-count-data" class="section level3">
<h3>Negative Binomial methods for differential expression of count data</h3>
<p>All the following methods are available on Bioconductor:</p>
<ul>
<li><code>edgeR</code></li>
</ul>
<p>Mark D. Robinson, Davis J. McCarthy, and Gordon K. Smyth, “edgeR: a Bioconductor package for differential expression analysis of digital gene expression data” Bioinformatics 2010. <a href="http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2796818/">http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2796818/</a></p>
<ul>
<li><code>DESeq</code> (the latest version is a separate package, <code>DESeq2</code>)</li>
</ul>
<p>Simon Anders and Wolfgang Huber, “Differential expression analysis for sequence count data”, Genome Biology 2010. <a href="http://genomebiology.com/2010/11/10/r106">http://genomebiology.com/2010/11/10/r106</a></p>
<ul>
<li><code>DSS</code></li>
</ul>
<p>Hao Wu, Chi Wang, Zhijin Wu, “A new shrinkage estimator for dispersion improves differential expression detection in RNA-seq data” Biostatistics 2013. <a href="http://biostatistics.oxfordjournals.org/content/14/2/232">http://biostatistics.oxfordjournals.org/content/14/2/232</a></p>
</div>
<div id="transformation-followed-by-linear-model-methods" class="section level3">
<h3>Transformation followed by linear model methods</h3>
<p><code>voom</code> in the <code>limma</code> Bioconductor package</p>
<p>Charity W Law, Yunshun Chen, Wei Shi and Gordon K Smyth, “voom: precision weights unlock linear model analysis tools for RNA-seq read counts”, Genome Biology. 2014. <a href="http://genomebiology.com/2014/15/2/R29">http://genomebiology.com/2014/15/2/R29</a></p>
</div>
<div id="resampling-based-methods" class="section level3">
<h3>Resampling-based methods</h3>
<p><code>SAMseq</code> in the <code>samr</code> package on CRAN</p>
<p>Jun Li and Robert Tibshirani, “Finding consistent patterns: A nonparametric approach for identifying differential expression in RNA-Seq data”, Stat Methods Med Res. 2013. <a href="http://smm.sagepub.com/content/22/5/519.short">http://smm.sagepub.com/content/22/5/519.short</a></p>
</div>
<div id="incorporating-isoform-abundance" class="section level3">
<h3>Incorporating isoform-abundance</h3>
<ul>
<li><code>Cuffdiff</code> (the latest version is <code>Cuffdiff2</code>)</li>
</ul>
<p>Trapnell C, Hendrickson DG, Sauvageau M, Goff L, Rinn JL, Pachter L., “Differential analysis of gene regulation at transcript resolution with RNA-seq” Nat Biotechnol. 2013. <a href="http://www.ncbi.nlm.nih.gov/pubmed/23222703">http://www.ncbi.nlm.nih.gov/pubmed/23222703</a></p>
<ul>
<li><code>BitSeq</code></li>
</ul>
<p>Peter Glaus, Antti Honkela, and Magnus Rattray, “Identifying differentially expressed transcripts from RNA-seq data with biological variation”, Bioinformatics. 2012. <a href="http://bioinformatics.oxfordjournals.org/content/28/13/1721">http://bioinformatics.oxfordjournals.org/content/28/13/1721</a></p>
</div>
</div>
<div id="licence" class="section level2">
<h2>Licence</h2>
<p><a href="https://www.sthda.com/english/english/wiki/mit-licence">Licence</a></p>
</div>
<div id="references" class="section level2">
<h2>References</h2>
<p><a href="https://github.com/genomicsclass">https://github.com/genomicsclass</a></p>
</div>

<script>jQuery(document).ready(function () {jQuery('h1,h2,h3,h4').addClass('formatter-title');});//add phpboost class to header</script>
<style>.content{padding:0px;}</style>
</div><!--end rdoc-->
<!--====================== stop here when you copy to sthda================-->


<!-- END HTML -->]]></description>
			<pubDate>Tue, 07 Oct 2014 17:52:31 +0200</pubDate>
			
		</item>
		
		<item>
			<title><![CDATA[RNA sequencing data analysis - alignment and reads counting using cufflinks]]></title>
			<link>https://www.sthda.com/english/wiki/rna-sequencing-data-analysis-alignment-and-reads-counting-using-cufflinks</link>
			<guid>https://www.sthda.com/english/wiki/rna-sequencing-data-analysis-alignment-and-reads-counting-using-cufflinks</guid>
			<description><![CDATA[<!-- START HTML -->

 <!--====================== start from here when you copy to sthda================-->  
  <div id="rdoc">

<div id="TOC">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#download-data">Download data</a></li>
<li><a href="#align-the-reads">Align the reads</a></li>
<li><a href="#read-counting-using-cufflinks">Read counting using Cufflinks</a></li>
<li><a href="#use-igv-to-visualize">Use IGV to visualize</a></li>
</ul>
</div>

<hr />
<pre class="warning"><code>This analysis was performed using R (ver. 3.1.0).</code></pre>
<div id="introduction" class="section level2">
<h2>Introduction</h2>
<p>RNA-Seq is a valuable experiment for quantifying both the types and the amount of RNA molecules in a sample. The aims of this article is to show you :</p>
<ul>
<li>How to align the reads using tophat2?
</li>
<li>How to count the number of reads per features using cufflinks?
</li>
<li>How to visualize bam file using IGV ?</li>
</ul>
</div>
<div id="download-data" class="section level2">
<h2>Download data</h2>
<p>We will work with the Hammer et al dataset, as prepared by the <a href="http://bowtie-bio.sourceforge.net/recount/">ReCount website</a>.</p>
<p><strong>The Hammer et al paper:</strong> <a href="http://www.ncbi.nlm.nih.gov/pubmed?term=20452967">http://www.ncbi.nlm.nih.gov/pubmed?term=20452967</a>
<strong>The GEO page:</strong> <a href="http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE20895">http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE20895</a>
<strong>The sample I will align:</strong> <a href="http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM539553">http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM539553</a>
<strong>which points to the SRA:</strong> <a href="ftp://ftp-trace.ncbi.nlm.nih.gov/sra/sra-instant/reads/ByExp/sra/SRX%2FSRX020%2FSRX020088/SRR042499/">ftp://ftp-trace.ncbi.nlm.nih.gov/sra/sra-instant/reads/ByExp/sra/SRX%2FSRX020%2FSRX020088/SRR042499/</a></p>
<p><strong>download the file</strong></p>
<pre class="bash"><code>#download the file
wget ftp://ftp-trace.ncbi.nlm.nih.gov/sra/sra-instant/reads/ByExp/sra/SRX%2FSRX020%2FSRX020088/SRR042499/SRR042499.sra

#convert to FastQ
fastq-dump SRR042499.sra</code></pre>
<p><strong>Download reference genome from tophat website</strong></p>
<pre class="bash"><code>wget wget [url=ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Rattus_norvegicus/Ensembl/RGSC3.4/Rattus_norvegicus_Ensembl_RGSC3.4.tar.gz]ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Rattus_norvegicus/Ensembl/RGSC3.4/Rattus_norvegicus_Ensembl_RGSC3.4.tar.gz[/url]
tar zxvf Rattus_norvegicus_Ensembl_RGSC3.4.tar.gz</code></pre>
<p>The genome was downloaded from Illumina <a href="http://cufflinks.cbcb.umd.edu/igenomes.html">iGenomes</a></p>
</div>
<div id="align-the-reads" class="section level2">
<h2>Align the reads</h2>
<p>The tophat call to align the reads (this take account for splice read) :</p>
<pre class="bash"><code>tophat2 -o tophat_out -p 10 /path/to/Rattus_norvegicus/Ensembl/RGSC3.4/Sequence/Bowtie2Index/genome SRR042499.fastq</code></pre>
<p><strong>-o tophat_out</strong> : Output directory
<strong>-p 10</strong> : number of threads to use</p>
<p><span class="success">Tophat2 is an aligner which takes account splice reads.</span></p>
<p><strong>Tophat2 output</strong></p>
<p><img src="https://www.sthda.com/english/sthda/RDoc/images/genomics/tophat-output.png" alt="Tophat2 output" /></p>
</div>
<div id="read-counting-using-cufflinks" class="section level2">
<h2>Read counting using Cufflinks</h2>
<p><strong>Cufflinks</strong>, estimates both the expression levels and the different RNA isoforms which are present in the sample. The main paper describing the Cufflinks method is <a href="#foot">Trapnell (2010)</a> and the website for the Cufflinks software is:</p>
<p><a href="http://cufflinks.cbcb.umd.edu/">http://cufflinks.cbcb.umd.edu/</a></p>
<p><strong>After aligning the read, we can run cufflinks.</strong></p>
<pre class="bash"><code>cufflinks -o cufflinks -p 10 --GTF-guide /path/to/Rattus_norvegicus/Ensembl/RGSC3.4/Annotation/Genes/genes.gtf \
tophat_out/accepted_hits.bam</code></pre>
<p><strong>-o cufflinks</strong>: Output directory
<strong>-p 10</strong> : Number of thread to use
<strong>–GTF-guide</strong>: indicate GTF file. This is the ensemble GTF file which contains all the information about the exons and transcripts and genes of rat.</p>
<p>And then finally, you give it the one or more files which have the aligned reads (accepted_hits.bam). This file contains also spliced reads.</p>
<p><span class="success"> Cufflinks will try to find the transcripts that are present and the level of the transcripts. </span></p>
<p><strong>cufflinks output files are</strong>:</p>
<ul>
<li>genes.fpkm_tracking
</li>
<li>isoform.fpkm_tracking
</li>
<li>skipped.gtf
</li>
<li>transcriptd.gtf</li>
</ul>
<p><img src="https://www.sthda.com/english/sthda/RDoc/images/genomics/cufflink-output.png" alt="Cufflinks output" /></p>
<p>The first two are tracking files which gives some information about the genes. It gives here, in the last four columns, the measure of gene expression (FPKM, FPKM_conf_lo, FPKM_conf_hi, FPKM_status). <strong>FPKM</strong> is the number of fragments per kilobase per million mapped reads. So it’s normalized value of expression.</p>
<p>We are going to work with the transcripts GTF file. This contains information about all the transcripts which were found in the sample and the exons which belong to the transcript. You can see this file is a mix of known transcripts and in this case it will use the Ensembl ID (The ID of the GTF file you give it as a guide).</p>
<p>It also contains some transcripts which are given a new ID. this is a known transcript but the gene ID is annotated by Cufflinks. If there’s a new transcript it would also be given a cuff prefix. There is an example of both the gene is found by Cufflinks and a new transcript was found by Cufflinks.</p>
</div>
<div id="use-igv-to-visualize" class="section level2">
<h2>Use IGV to visualize</h2>
<p>I’m going to just show you what these look like in IGV. So I’ve downloaded the accepted hits.bam file and the transcripts .GTF file to my local directory. So I then use this line here to– it’s a grep line which removes any lines which match this. I wanted to remove lines which had FPKM 0.</p>
<p><span class="bash">grep -v ‘FPKM “0.0000000000”’ transcripts.gtf | less</span></p>
<p>And then I downloaded the chromosome 1 FASTA file and the rat GTF file so that I could look at these in IGV. So now here’s my IGV window where I’ve loaded in the coverage. And this line here is the ensemble GTF file and below it is the transcripts.gtf file from Cufflinks.</p>
<p>So they look very similar but we can zoom in and try to find some differences.</p>
<p>For visualizing:</p>
<p><a href="ftp://ftp.ensembl.org/pub/release-69/fasta/rattus_norvegicus/dna/Rattus_norvegicus.RGSC3.4.69.dna.chromosome.1.fa.gz">ftp://ftp.ensembl.org/pub/release-69/fasta/rattus_norvegicus/dna/Rattus_norvegicus.RGSC3.4.69.dna.chromosome.1.fa.gz</a>
<a href="ftp://ftp.ensembl.org/pub/release-69/gtf/rattus_norvegicus/Rattus_norvegicus.RGSC3.4.69.gtf.gz">ftp://ftp.ensembl.org/pub/release-69/gtf/rattus_norvegicus/Rattus_norvegicus.RGSC3.4.69.gtf.gz</a></p>
<hr />
<p><strong>Licence</strong>: <a href="https://www.sthda.com/english/english/wiki/mit-licence">Licence</a>
<strong>References</strong>: <a href="https://github.com/genomicsclass">https://github.com/genomicsclass</a></p>
</div>

<script>jQuery(document).ready(function () {jQuery('h1,h2,h3,h4').addClass('formatter-title');});//add phpboost class to header</script>
<style>.content{padding:0px;}</style>
</div><!--end rdoc-->
<!--====================== stop here when you copy to sthda================-->


<!-- END HTML -->]]></description>
			<pubDate>Tue, 07 Oct 2014 16:16:48 +0200</pubDate>
			
		</item>
		
		<item>
			<title><![CDATA[RNA sequencing]]></title>
			<link>https://www.sthda.com/english/wiki/rna-sequencing</link>
			<guid>https://www.sthda.com/english/wiki/rna-sequencing</guid>
			<description><![CDATA[-=-]]></description>
			<pubDate>Mon, 29 Sep 2014 20:54:07 +0200</pubDate>
			
		</item>
		
	</channel>
</rss>
