| name | bio-de-edger-basics |
| description | Perform differential expression analysis using edgeR in R/Bioconductor. Use for analyzing RNA-seq count data with the quasi-likelihood F-test framework, creating DGEList objects, normalization, dispersion estimation, and statistical testing. Use when performing DE analysis with edgeR. |
| tool_type | r |
| primary_tool | edgeR |
edgeR Basics
Differential expression analysis using edgeR's quasi-likelihood framework for RNA-seq count data.
Required Libraries
library(edgeR)
library(limma)
Installation
if (!require('BiocManager', quietly = TRUE))
install.packages('BiocManager')
BiocManager::install('edgeR')
Creating DGEList Object
y <- DGEList(counts = counts, group = group)
y <- DGEList(counts = counts, group = group, genes = gene_info)
y
Standard edgeR Workflow (Quasi-Likelihood)
y <- DGEList(counts = counts, group = group)
keep <- filterByExpr(y, group = group)
y <- y[keep, , keep.lib.sizes = FALSE]
y <- calcNormFactors(y)
design <- model.matrix(~ group)
y <- estimateDisp(y, design)
fit <- glmQLFit(y, design)
qlf <- glmQLFTest(fit, coef = 2)
topTags(qlf)
Filtering Low-Expression Genes
keep <- filterByExpr(y, group = group)
y <- y[keep, , keep.lib.sizes = FALSE]
keep <- rowSums(cpm(y) > 1) >= 2
y <- y[keep, , keep.lib.sizes = FALSE]
keep <- rowSums(y$counts >= 10) >= 3
y <- y[keep, , keep.lib.sizes = FALSE]
Normalization Methods
y <- calcNormFactors(y, method = 'TMM')
y <- calcNormFactors(y, method = 'RLE')
y <- calcNormFactors(y, method = 'upperquartile')
y <- calcNormFactors(y, method = 'none')
y$samples$norm.factors
Design Matrices
design <- model.matrix(~ group)
design <- model.matrix(~ batch + group)
design <- model.matrix(~ genotype + treatment + genotype:treatment)
design <- model.matrix(~ 0 + group)
colnames(design) <- levels(group)
Dispersion Estimation
y <- estimateDisp(y, design)
y <- estimateGLMCommonDisp(y, design)
y <- estimateGLMTrendedDisp(y, design)
y <- estimateGLMTagwiseDisp(y, design)
y$common.dispersion
y$trended.dispersion
y$tagwise.dispersion
plotBCV(y)
Quasi-Likelihood Testing
fit <- glmQLFit(y, design)
qlf <- glmQLFTest(fit, coef = 2)
contrast <- makeContrasts(groupB - groupA, levels = design)
qlf <- glmQLFTest(fit, contrast = contrast)
qlf <- glmQLFTest(fit, coef = 2:3)
Making Contrasts
design <- model.matrix(~ 0 + group)
colnames(design) <- levels(group)
y <- estimateDisp(y, design)
fit <- glmQLFit(y, design)
contrast <- makeContrasts(
TreatedVsControl = treated - control,
DrugAVsControl = drugA - control,
DrugBVsControl = drugB - control,
DrugAVsDrugB = drugA - drugB,
levels = design
)
qlf_treated <- glmQLFTest(fit, contrast = contrast[, 'TreatedVsControl'])
qlf_drugA <- glmQLFTest(fit, contrast = contrast[,
Accessing Results
topTags(qlf, n = 20)
results <- topTags(qlf, n = Inf)$table
summary(decideTests(qlf))
de_genes <- topTags(qlf, n = Inf, p.value = 0.05)$table
Result Columns
| Column | Description |
|---|
logFC | Log2 fold change |
logCPM | Average log2 counts per million |
F | Quasi-likelihood F-statistic |
PValue | Raw p-value |
FDR | False discovery rate (adjusted p-value) |
Alternative: Exact Test (Classic edgeR)
y <- DGEList(counts = counts, group = group)
y <- calcNormFactors(y)
y <- estimateDisp(y)
et <- exactTest(y)
topTags(et)
Alternative: glmLRT (Likelihood Ratio Test)
fit <- glmFit(y, design)
lrt <- glmLRT(fit, coef = 2)
topTags(lrt)
Treat Test (Log Fold Change Threshold)
tr <- glmTreat(fit, coef = 2, lfc = log2(1.5))
topTags(tr)
Multi-Factor Designs
design <- model.matrix(~ batch + condition, data = sample_info)
y <- estimateDisp(y, design)
fit <- glmQLFit(y, design)
qlf <- glmQLFTest(fit, coef = ncol(design))
Getting Normalized Counts
cpm_values <- cpm(y)
log_cpm <- cpm(y, log = TRUE)
rpm_values <- cpm(y)
log_cpm <- cpm(y, log = TRUE, prior.count = 2)
Exporting Results
all_results <- topTags(qlf, n = Inf)$table
all_results$gene_id <- rownames(all_results)
write.csv(all_results, file = 'edger_results.csv', row.names = FALSE)
write.csv(cpm(y), file = 'cpm_values.csv')
Common Errors
| Error | Cause | Solution |
|---|
| "design matrix not full rank" | Confounded variables | Check sample metadata |
| "No residual df" | Too few samples | Need more replicates |
| "NA/NaN/Inf" | Zero counts in all samples | Filter more stringently |
Deprecated/Changed Functions
| Old | Status | New |
|---|
decidetestsDGE() | Removed (v4.4) | decideTests() |
glmFit() + glmLRT() | Still works | Prefer glmQLFit() + glmQLFTest() |
estimateDisp() | Optional (v4+) | glmQLFit() estimates internally |
mglmLS(), mglmSimple() | Retired | mglmLevenberg() or mglmOneWay() |
Note: calcNormFactors() and normLibSizes() are synonyms - both work.
Quick Reference: Workflow Steps
y <- DGEList(counts = counts, group = group)
keep <- filterByExpr(y, group = group)
y <- y[keep, , keep.lib.sizes = FALSE]
y <- calcNormFactors(y)
design <- model.matrix(~ group)
y <- estimateDisp(y, design)
fit <- glmQLFit(y, design)
qlf <- glmQLFTest(fit, coef = 2)
topTags(qlf, n = 20)
Choosing edgeR vs DESeq2
| Aspect | edgeR | DESeq2 |
|---|
| Model | Negative binomial + QL | Negative binomial |
| Shrinkage | Empirical Bayes on dispersions | Shrinkage estimators for LFC |
| Small samples | Robust with QL framework | Good with shrinkage |
| Speed | Generally faster | Slower for large datasets |
| Output | F-statistic, FDR | Wald statistic, padj |
Related Skills
- deseq2-basics - Alternative DE analysis with DESeq2
- de-visualization - MA plots, volcano plots, heatmaps
- de-results - Extract and export significant genes