Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Normalization, filtering and sample quality

Before testing, look at the data: do the samples group as the design expects, which genes have enough counts to be tested, do the libraries need rescaling, and does any sample or gene behave unlike the rest? limma_voom takes these steps inside, with defaults; this page takes them one at a time, so that each choice can rest on what the data show. It uses the CD14+ monocytes of the Kang data Kang et al., 2018 and the simulated bulk experiment, whose noisier sample is known (the kang2018 and simulated_bulk datasets of the Datasets page).

Do the samples group as expected?

limma’s multidimensional scaling plot (plot_mds) places the samples so that their distances are the typical log2 fold changes between them, the root mean square of the 500 largest. From a cube it takes one cell type’s counts, filtered and normalized as edgeR prepares them for its own plot.

CytePool 0.1.dev54+g3f0cbb52e
Two multidimensional scaling plots of the 16 CD14+ monocyte samples, coloured by condition (control blue, stimulated orange) and marked by donor. Left, dimensions 1 and 2: dimension 1, 73% of the variance, puts the control samples near 1 and the stimulated near -1; dimension 2, 5%, puts both samples of donor 1039 at the top. Right, dimensions 2 and 3 (4%): the two samples of each donor lie near each other, those of donor 1039 at the right and those of donor 101 at the bottom left.

The first dimension, nearly three quarters of the variation, is the stimulation. The next ones are the donors: the two samples of each donor lie near each other, and donor 1039 stands apart from the rest. Differences between donors are why the design pairs each donor’s samples (Genes that change in each cell type). A sample far from its group on such a plot deserves a look before any test.

Which genes to test

voom estimates how the variance of the log counts falls with their level, and weights every observation by it Law et al., 2014; its plot (plot_mean_variance) shows the trend. Genes whose counts are mostly zeros have log-CPM values near the floor in most samples: their spread is small for want of counts, not because they are precise, and they bend the trend down at its low end, where voom would then weight noisy observations most. filter_by_expression keeps the genes with enough counts in enough samples, edgeR’s filterByExpr rule Chen et al., 2016, and the number of samples it asks for comes from the design.

12,966 genes with counts in at least two samples
 5,125 kept by the filter with the paired design
 3,651 kept by the filter with the condition as the group
Two voom mean-variance plots of the CD14+ monocytes: the square root of each gene's residual standard deviation against its average log2 count, with the LOWESS trend in orange. Left, the 12,966 genes with counts in at least two samples: the trend rises from about 0.8 at the lowest counts to a peak near 0.95 at an average log2 count of about 1, then falls to near 0 at 16. Right, the 5,125 genes kept by the filter: the trend falls steadily from about 1.2 at an average log2 count of 0 to about 0.3 at 16.

Without the filter, the trend falls at the low end, as the genes with mostly zero counts pull it down; with it, the trend falls steadily with the expression level, the shape voom expects. The number of samples a gene needs comes from the design’s largest leverage: with the paired design, every sample’s profile has a leverage of 9/16, so a gene needs enough counts in two samples; with the condition as the group, in eight, which keeps fewer genes.

Normalization factors

Library sizes account for sequencing depth, not for composition: when a few genes take a larger share of a library, every other gene looks lower in it. TMM factors (tmm_factors) rescale the libraries so that most genes do not change between samples Robinson & Oshlack, 2010, and Count models describes the alternatives.

The 20 genes that gain most take 4% of the control libraries and 22% of the stimulated ones.

median factor     control  stimulated
TMM                  1.19        0.83
RLE                  1.19        0.84
upper quartile       1.06        0.93
DESeq2               1.19        0.84

Twenty genes that the stimulation raises take a fifth of the stimulated monocytes’ reads, and the factors correct for it: TMM, RLE and DESeq2’s size factors agree that the stimulated libraries count for about 0.83 of their size and the control ones about 1.19, so that without them most genes would look lower after the stimulation. The upper quartile, which scales each library by one quantile of its counts, corrects less.

Genes with outlying variances

After voom, the residual variances of the genes should not depend on their expression, and empirical Bayes moderation shrinks each towards a common prior (Empirical Bayes moderation). limma’s plotSA (plot_residual_variances) shows them, and robust=True estimates the prior so that genes with outlying variances do not distort it Phipson et al., 2016.

prior degrees of freedom: 11.4, robust 27.7
largest residual variances: HBB, HBA2, HBA1, ISG15, CCL3, IFITM3, CCL2, CCL4, APOBEC3A, CXCL10, IFI6, LY6E
limma's plotSA for the CD14+ monocytes after robust moderation: the square root of each gene's residual standard deviation, mostly between 0.6 and 1.3, against its average log-expression, from 1 to 17, with the prior as a flat orange line near 0.97. 217 genes are marked green as outlying variances, most of them above the others, up to about 4.5, at average log-expressions between 6 and 12; some lie below, near 0.5.

The genes with the largest variances are those of hemoglobin, whose reads come from red cells that contaminate some samples more than others, and interferon-stimulated genes and chemokines whose response differs between donors; the plot marks 217 outlying variances. Robust moderation gives such genes smaller prior degrees of freedom, so that their variances stay closer to their own estimates, and raises those of the other genes from 11.4 to 27.7, whose variances are then shrunk more, which gives their tests more power.

A sample of poor quality

A sample that follows the model less closely than the others, such as a degraded one, adds noise to every gene. Sample quality weights estimate how closely each sample follows the model and down-weight it, instead of removing it Liu et al., 2015; Precision weights gives the model. In the simulated bulk experiment, sample drug_b_3 has four times the dispersion of the others.

Two panels of the simulated bulk experiment. Left, a multidimensional scaling plot of its 12 samples, labelled, coloured by condition and marked by batch: dimension 1, 27% of the variance, separates drug A from the control and drug B samples, and dimension 2, 19%, sets sample drug_b_3 apart at the top right, far from the other drug B samples. Right, a bar for the quality weight of each sample, with a dashed line at 1: every sample weighs between 1.05 and 1.2 except drug_b_3, which weighs 0.30.
equal weights    192 genes called, 11 of them false
quality weights  204 genes called, 12 of them false

The noisy sample stands apart on the MDS plot and gets a weight of 0.30, while the others weigh slightly more than one, as the weights multiply to one. Down-weighting it finds more of the genes that drug B changes, with about the same number of false calls.

Check the design

A label typed differently in one sample splits a group in two, and the analysis then runs without an error. Design.check reports such problems, with what to do; here one stimulated sample is labelled Stim.

Design check: 16 samples, 10 columns, rank 10, 6 residual degrees of freedom.
3 warnings:
  1. [similar_levels] condition has levels that differ only in case or surrounding
     spaces ('Stim' and 'stim'), and each is a group of its own; if they mean the same
     group, clean the labels before building the design
  2. [single_sample_level] condition has a single sample at level 'Stim' (1016_stim);
     effects of such a level rest on one sample with no replicate. Add replicates, merge
     the level with a similar one, or remove the sample
  3. [unreplicated_sample] the model fits sample 1016_ctrl (donor = 1016, condition =
     ctrl) exactly (leverage 1), so it tells nothing about the residual variance and the
     effects it determines rest on it alone. This happens when a level, or a combination
     of levels in an interaction, has too few samples for the terms that involve it; add
     replicates or simplify the formula

The check also finds aliased and confounded columns, levels without samples, contrasts the design cannot estimate and numeric codes that look like batches (Designs, linear models and contrasts).

Choices

  • The filter. limma_voom filters with the design, as above; a paired design gives every sample a high leverage, so a gene needs counts in only a few samples. expression_filter changes the thresholds, and filter_by_expression with group= asks for counts in as many samples as the smallest group has.

  • Normalization factors. TMM is the default of limma_voom and of edgeR. TMM, RLE and DESeq2’s median ratios assume that most genes do not change between samples, and the upper quartile that one quantile of the counts does not; when a response changes many genes, check that the factors make sense, as above.

  • Robust moderation. Pass robust=True to limma_voom when plotSA shows outlying variances, as here.

  • A poor sample. Quality weights keep it at a lower weight; leaving it out loses its information, and in a paired design its partner’s (Precision weights). prior_weights="n_cells" instead weights pseudobulk profiles by their number of cells; the two cannot be combined.

  • What to adjust for. Repeated measures and donors partitions the variance of every gene among the variables of the design.

References
  1. Kang, H. M., Subramaniam, M., Targ, S., Nguyen, M., Maliskova, L., McCarthy, E., Wan, E., Wong, S., Byrnes, L., Lanata, C. M., Gate, R. E., Mostafavi, S., Marson, A., Zaitlen, N., Criswell, L. A., & Ye, C. J. (2018). Multiplexed droplet single-cell RNA-sequencing using natural genetic variation. Nature Biotechnology, 36(1), 89–94. 10.1038/nbt.4042
  2. Law, C. W., Chen, Y., Shi, W., & Smyth, G. K. (2014). voom: precision weights unlock linear model analysis tools for RNA-seq read counts. Genome Biology, 15(2), R29. 10.1186/gb-2014-15-2-r29
  3. Chen, Y., Lun, A. T. L., & Smyth, G. K. (2016). From reads to genes to pathways: differential expression analysis of RNA-Seq experiments using Rsubread and the edgeR quasi-likelihood pipeline. F1000Research, 5, 1438. 10.12688/f1000research.8987.2
  4. Robinson, M. D., & Oshlack, A. (2010). A scaling normalization method for differential expression analysis of RNA-seq data. Genome Biology, 11(3), R25. 10.1186/gb-2010-11-3-r25
  5. Phipson, B., Lee, S., Majewski, I. J., Alexander, W. S., & Smyth, G. K. (2016). Robust hyperparameter estimation protects against hypervariable genes and improves power to detect differential expression. The Annals of Applied Statistics, 10(2), 946–963. 10.1214/16-AOAS920
  6. Liu, R., Holik, A. Z., Su, S., Jansz, N., Chen, K., Leong, H. S., Blewitt, M. E., Asselin-Labat, M.-L., Smyth, G. K., & Ritchie, M. E. (2015). Why weight? Modelling sample and observational level variability improves power in RNA-seq analyses. Nucleic Acids Research, 43(15), e97. 10.1093/nar/gkv412