Lesson 12 of 14 · 11 min
A Gentle Intro to Bioconductor
Bioconductor is a free, open-source collection of R packages built specifically for analyzing biological data, especially the high-throughput data that comes out of DNA sequencing and gene-expression experiments. R is the programming language these packages are written in, and a package is simply a bundle of reusable code that adds new functions to R. Where general-purpose R packages help with everyday statistics and plotting, Bioconductor packages are tuned for genomics work like counting how many sequencing reads (the short stretches of DNA a sequencer reports) fall on each gene, or handling DNA sequences.
Bioconductor Versus CRAN
CRAN, the Comprehensive R Archive Network, is R's main package repository and the place the install.packages() command downloads from by default. Bioconductor is a separate repository with its own twice-a-year release schedule, and each Bioconductor release is pinned to a specific version of R so that all of its packages are tested to work together. Because of this pinning you do not install Bioconductor packages with install.packages(); instead you use a small helper package called BiocManager.
# BiocManager itself lives on CRAN, so install it the ordinary way first
install.packages("BiocManager")
# Then ask BiocManager to install a Bioconductor package by name.
# The :: means "use the install function that lives inside BiocManager".
BiocManager::install("DESeq2")'getOption("repos")' replaces Bioconductor standard repositories, see
'help("repositories", package = "BiocManager")' for details.
Replacement repositories:
CRAN: https://cran.rstudio.com
Bioconductor version 3.19 (BiocManager 1.30.23), R 4.4.1 (2024-06-14)
Installing package(s) 'DESeq2'
...
* DONE (DESeq2)
Packages You Will Meet
DESeq2 and edgeR both hunt for genes whose activity differs between conditions, a task called differential expression analysis, and both model raw read counts using the negative binomial distribution, a statistical model well suited to count data that varies more than a simple average would predict. limma answers the same question using linear models, which are equations that relate each gene's measured signal to the experimental conditions, and through its voom method it now handles RNA-seq counts as well as the microarrays (an older chip-based technology for measuring gene activity) it was first built for. Biostrings provides fast, memory-efficient containers for DNA, RNA, and protein sequences, while GenomicRanges represents genomic intervals, meaning stretches of a chromosome defined by a start and an end position.
Tying Data Together
Most Bioconductor workflows revolve around one object called a SummarizedExperiment, which locks your numbers and your sample information together in a single container. It stores a matrix of measurements called an assay, where each row is a feature such as a gene and each column is a sample, plus a table named colData that holds one row of metadata per sample. Because the counts and the sample labels always travel together, you can never accidentally shuffle them out of sync.
library(SummarizedExperiment)
# A counts matrix: 3 genes (rows) measured across 4 samples (columns)
counts <- matrix(
c(120, 80, 5, 200,
15, 20, 300, 10,
0, 2, 1, 4),
nrow = 3, byrow = TRUE,
dimnames = list(c("GeneA", "GeneB", "GeneC"),
c("S1", "S2", "S3", "S4"))
)
# One row of metadata per sample: the condition each column belongs to.
# DataFrame is Bioconductor's table type, loaded with the package above.
sample_info <- DataFrame(condition = c("control", "control", "treated", "treated"))
# Bundle the counts and the sample metadata into one object
se <- SummarizedExperiment(assays = list(counts = counts), colData = sample_info)
seclass: SummarizedExperiment
dim: 3 4
metadata(0):
assays(1): counts
rownames(3): GeneA GeneB GeneC
rowData names(0):
colnames(4): S1 S2 S3 S4
colData names(1): condition
Try it yourself: After building se above, run assay(se) to pull the counts matrix back out, then run colData(se)$condition to see the treatment labels. Check that column S1 in the counts still matches the first condition label, confirming the numbers and the sample labels stayed lined up.