Install DESeq2 and edgeR via conda (R/Bioconductor, Apple Silicon)
Build a pinned R and Bioconductor stack with DESeq2 and edgeR inside one isolated conda environment on Apple Silicon, never touching system R.
DESeq2 and edgeR are the two workhorse R/Bioconductor packages for calling differentially expressed genes from RNA-seq count data, and nearly every published differential-expression pipeline leans on one of them. Both ship as prebuilt bioconda packages, so you can get a working Bioconductor stack without compiling anything from source or wrestling with install.packages() and missing system libraries. This guide builds a single conda environment with r-base, DESeq2, and edgeR pinned together, completely isolated from whatever R you already have on your Mac.
Why install through conda instead of install.packages()
The usual route to DESeq2 is BiocManager::install("DESeq2") from inside R. On macOS that often means Xcode command line tools, a matching gfortran, and compiling a long chain of C/C++ and Fortran dependencies from source — well over an hour, breaking in creative ways whenever your compiler toolchain drifts from the R build.
Conda sidesteps all of it. The bioconda packages bioconductor-deseq2 and bioconductor-edger are prebuilt binaries that pull in a matching r-base plus every Bioconductor and CRAN dependency, also prebuilt. Nothing compiles locally, and the whole stack lives inside one environment you can delete and rebuild at will.
Prerequisites
You need a working conda install first. If you do not have one yet, follow our Miniconda on Apple Silicon guide and come back here. This assumes an Apple Silicon Mac (osx-arm64) with a recent conda defaulting to the fast libmamba solver (conda 23.10 and later).
As with every bioconda install on this site, we install only from conda-forge and bioconda and pass --override-channels so conda never touches the Anaconda defaults channel, which is gated behind a Terms-of-Service prompt on recent conda releases.
TL;DR: copy-paste install
conda create -n bu-deseq2 --override-channels -c conda-forge -c bioconda bioconductor-deseq2 bioconductor-edger
conda activate bu-deseq2
R -e 'library(DESeq2); library(edgeR)'That is the whole install. Expect it to take a while to solve — more on that below — and the rest of this guide walks through each step in detail.
Step 1: Create the environment
Ask for both packages in the same conda create call rather than installing them separately. Solving them together lets conda pick one consistent r-base version and one consistent set of shared dependencies for both packages at once.
conda create -n bu-deseq2 --override-channels -c conda-forge -c bioconda bioconductor-deseq2 bioconductor-edgerThis solve is genuinely slow, often several minutes even on a fast connection — that is expected, not a sign something is broken. DESeq2 and edgeR each pull in dozens of Bioconductor and CRAN packages (S4Vectors, IRanges, GenomicRanges, SummarizedExperiment, BiocParallel, limma, locfit, RcppArmadillo, and more) plus r-base itself, and the solver has to find a mutually compatible set of versions across all of them. Let it run; do not kill and retry.
You should see something like this shape of output, trimmed down: conda resolves a large "NEW packages will be INSTALLED" list headed by r-base and dozens of r-* and bioconductor-* packages, downloads several hundred megabytes, and finishes with Executing transaction: done. Do not worry about exact package counts or version numbers — bioconda updates these builds regularly.
Solving environment: done
The following NEW packages will be INSTALLED:
r-base bioconda/osx-arm64::r-base-...
bioconductor-deseq2 bioconda/osx-arm64::bioconductor-deseq2-...
bioconductor-edger bioconda/osx-arm64::bioconductor-edger-...
... (dozens more r-* and bioconductor-* dependencies)
Preparing transaction: done
Verifying transaction: done
Executing transaction: doneStep 2: Verify the install in R
Activate the environment — you need to do this in every new shell — and load both libraries directly:
conda activate bu-deseq2
R -e 'library(DESeq2); library(edgeR); sessionInfo()'You should see something like this: each library() call prints a few "Loading required package" messages as dependencies attach, no errors, and sessionInfo() lists both packages under "other attached packages" with version strings such as DESeq2_x.y and edgeR_x.y (exact numbers depend on when you installed).
Loading required package: S4Vectors
Loading required package: BiocGenerics
...
other attached packages:
[1] edgeR_x.y limma_x.y DESeq2_x.y
[4] SummarizedExperiment_x.y GenomicRanges_x.y ...Also confirm this R is the one inside your environment, not a system Homebrew or CRAN install:
which RIt should resolve inside .../envs/bu-deseq2/bin/R. If you get a different path, or R: command not found, activate the environment again.
Step 3: A tiny real usage example
A minimal, runnable example that exercises both packages end to end on a toy count matrix — two genes, three control and three treatment replicates. Far too small to draw any biological conclusion from, but it confirms the install works and shows each package's API.
counts <- matrix(
c(20, 25, 18, 200, 210, 195,
30, 28, 32, 15, 12, 18),
nrow = 2, byrow = TRUE,
dimnames = list(
c("geneA", "geneB"),
c("ctrl1", "ctrl2", "ctrl3", "trt1", "trt2", "trt3")
)
)
condition <- factor(c("ctrl", "ctrl", "ctrl", "trt", "trt", "trt"))DESeq2 wraps the counts and metadata in a DESeqDataSet, then runs its full normalization, dispersion-estimation, and Wald-test pipeline with a single DESeq() call:
library(DESeq2)
coldata <- data.frame(condition = condition, row.names = colnames(counts))
dds <- DESeqDataSetFromMatrix(countData = counts, colData = coldata, design = ~ condition)
dds <- DESeq(dds)
results(dds)edgeR takes a slightly more manual route: build a DGEList, normalize with calcNormFactors(), estimate dispersion, then test:
library(edgeR)
y <- DGEList(counts = counts, group = condition)
y <- calcNormFactors(y)
y <- estimateDisp(y)
et <- exactTest(y)
topTags(et)Both should run without error and print a results table with a log2 fold change and a p-value for geneA and geneB. For a real experiment, feed in a full count matrix from featureCounts or Salmon plus tximport, with thousands of genes so dispersion estimates have enough data to shrink sensibly. See our RNA-seq differential expression walkthrough for the full statistical picture.
DESeq2 vs edgeR: which one to reach for
Both model counts with a negative binomial distribution and both are well validated, but they differ in defaults and workflow feel:
| DESeq2 | edgeR | |
|---|---|---|
| Normalization | Median-of-ratios size factors | TMM (trimmed mean of M-values) |
| Dispersion estimate | Empirical Bayes shrinkage toward a fitted trend | Per-gene, tagwise, or trended, several estimators available |
| Typical entry point | DESeqDataSetFromMatrix() then DESeq() | DGEList() then estimateDisp() |
| Fold-change shrinkage | Built in via lfcShrink() | Available via glmTreat() / effect-size options |
| Feel | Fewer manual steps, more "batteries included" | More explicit control over each modeling step |
In practice both give similar gene lists on the same dataset. Many labs run both as a cross-check, especially in a course setting.
Apple Silicon and long-solve gotchas
A few things specific to this stack, beyond the generic bioconda advice:
- The solve really is slow — that is normal. R/Bioconductor environments have one of the largest dependency graphs in bioconda. A
Solving environmentstep hanging for minutes is real work, not a stall — avoid interrupting it. - Install both packages in one
conda create, not two. Installing them separately can force the solver to downgrader-baseor shared dependencies later, triggering a bigger, slower re-solve. - Native
osx-arm64builds exist for this stack. Both packages carry compiled C/C++ code (DESeq2 via Rcpp, edgeR via its own C routines), so bioconda ships genuineosx-arm64builds rather than relying on Rosetta 2. Confirm withconda list -n bu-deseq2 r-base. - If a stray dependency ever lacks an arm64 build, fall back to
CONDA_SUBDIR=osx-64 conda create -n bu-deseq2-x86 --override-channels -c conda-forge -c bioconda bioconductor-deseq2 bioconductor-edger, thenconda config --env --set subdir osx-64. Rarely needed for this stack today. - Do not mix this with system R or RStudio's CRAN R. Keep any
BiocManager-installed system R separate, and point RStudio at.../envs/bu-deseq2/bin/Rif you want to use this environment there.
Common errors and fixes
| Error | Fix |
|---|---|
CondaToSNonInteractiveError / Terms of Service not accepted for defaults | Do not use the defaults channel. Install with --override-channels -c conda-forge -c bioconda as shown. |
PackagesNotFoundError: ... bioconductor-deseq2 | The bioconda channel is missing or listed in the wrong order. Pass both channels with conda-forge first: -c conda-forge -c bioconda. |
Solve appears stuck on Solving environment for a very long time | Expected for this stack. Give it several minutes; make sure you are on a conda version with the libmamba solver (23.10+), or install mamba and run mamba create instead. |
Error: package or namespace load failed for 'DESeq2' after activating | Usually means the environment was only partially installed (interrupted solve). Remove it and recreate: conda remove -n bu-deseq2 --all, then rerun the conda create command. |
library(DESeq2) works, but R resolves to a Homebrew or CRAN install | You forgot to activate the environment, or another R is earlier on your PATH. Run conda activate bu-deseq2 and re-check with which R. |
Managing the environment
Update both packages in place:
conda update -n bu-deseq2 --override-channels -c conda-forge -c bioconda bioconductor-deseq2 bioconductor-edgerSnapshot the exact environment so a collaborator (or a future you) can reproduce it precisely:
conda env export -n bu-deseq2 > deseq2-edger-env.ymlAnd when you no longer need it, remove it cleanly. Because everything — r-base included — lived inside the environment, this leaves nothing behind on your system:
conda remove -n bu-deseq2 --allNext steps
With a working DESeq2/edgeR environment in hand, a couple of natural follow-ons:
- Work through the RNA-seq differential expression walkthrough to see how counts, normalization, and the DESeq2 model fit into a full raw-reads-to-results pipeline.
- If you still need conda itself, start with Miniconda on Apple Silicon before coming back to this guide.