<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Pseudocount</title>
<link>https://pseudocount.com/</link>
<atom:link href="https://pseudocount.com/index.xml" rel="self" type="application/rss+xml"/>
<description>Bioinformatics statistics, checked by simulation: the pitfalls in RNA-seq, single-cell and omics analysis in R and Python, measured rather than asserted.</description>
<generator>quarto-1.9.38</generator>
<lastBuildDate>Thu, 24 Sep 2026 21:00:00 GMT</lastBuildDate>
<item>
  <title>Poisson or negative binomial for RNA-seq counts?</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/poisson-vs-negative-binomial/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-5">})</span>
<span id="cb1-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># normLibSizes() and glmQLFit(legacy = FALSE)</span></span>
<span id="cb1-7">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"limma"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.50"</span>,</span>
<span id="cb1-8">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.36"</span>,</span>
<span id="cb1-9">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4.0"</span>)</span>
<span id="cb1-10"></span>
<span id="cb1-11">pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f%%"</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-12">num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trim =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-13">dec <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>), x)</span>
<span id="cb1-14">rng <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(x)), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"to"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(x)))</span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Poisson and quasi-Poisson likelihood ratio tests for a two-group design, all genes at once.</span></span>
<span id="cb1-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># With a log link, an offset and one mean per group, the fitted values have a closed form:</span></span>
<span id="cb1-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the group total divided by the group's summed library sizes, times each sample's library size.</span></span>
<span id="cb1-19">pois_tests <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, group, lib) {</span>
<span id="cb1-20">  n <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(counts)</span>
<span id="cb1-21">  fit_null <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(lib), lib)</span>
<span id="cb1-22">  fit_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> counts</span>
<span id="cb1-23">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (g <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(group)) {</span>
<span id="cb1-24">    j <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> g</span>
<span id="cb1-25">    fit_full[, j] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(counts[, j, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">drop =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(lib[j]), lib[j])</span>
<span id="cb1-26">  }</span>
<span id="cb1-27">  dev <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(mu) <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> mu), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mu))</span>
<span id="cb1-28">  lr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dev</span>(fit_null) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dev</span>(fit_full)                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># deviance explained by the group</span></span>
<span id="cb1-29">  df_res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nlevels</span>(group)</span>
<span id="cb1-30">  pearson <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(fit_full <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, (counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> fit_full)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> fit_full, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))</span>
<span id="cb1-31">  disp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pearson <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> df_res                                    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pearson dispersion statistic</span></span>
<span id="cb1-32">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lr =</span> lr,</span>
<span id="cb1-33">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_pois =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(lr, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>),      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Poisson: dispersion fixed at 1</span></span>
<span id="cb1-34">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_qp =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pf</span>(lr <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> disp, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, df_res, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>),   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># quasi-Poisson F test</span></span>
<span id="cb1-35">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pearson =</span> pearson, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> disp)</span>
<span id="cb1-36">}</span>
<span id="cb1-37"></span>
<span id="cb1-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what we can measure because the truth is known</span></span>
<span id="cb1-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># BH is applied to every method's raw p-values in the same way; a missing p-value (DESeq2 can</span></span>
<span id="cb1-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># set one for a count outlier) is counted as not significant</span></span>
<span id="cb1-41">score <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, is_de) {</span>
<span id="cb1-42">  p[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(p)] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb1-43">  padj <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(p, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>)</span>
<span id="cb1-44">  call <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb1-45">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">null_p05 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_call =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(call),</span>
<span id="cb1-46">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(call)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de[call]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">power =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(call[is_de]))</span>
<span id="cb1-47">}</span>
<span id="cb1-48"></span>
<span id="cb1-49">theme_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-50">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb1-51">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>))</span></code></pre></div></div>
</details>
</div>
<p>Why not test RNA-seq counts with a Poisson model? Counts of reads are counts, and the Poisson distribution is the textbook model for counts, so a Poisson regression per gene looks like the obvious test. The problem is that the Poisson model fixes the variance to be equal to the mean, and counts from biological replicates vary far more than that. In the simulation below, a Poisson test gives p &lt; 0.05 for 52.9% of the genes that did not change, and 81.4% of the genes it calls at a 5% false discovery rate are false. A negative binomial test from edgeR on the same data gives 5.3% and 4.6%.</p>
<p>This post shows where the Poisson test goes wrong, two quick diagnostics that catch the problem on your own data, and why the quasi-Poisson model, the usual textbook repair, fixes the false positives but finds less than half as many of the changed genes as a negative binomial test.</p>
<section id="two-models-for-the-same-counts" class="level2">
<h2 class="anchored" data-anchor-id="two-models-for-the-same-counts">Two models for the same counts</h2>
<p>Take one gene measured in several mice from the same group. Even with perfect sequencing, the gene’s true expression differs from mouse to mouse. The read count you see has two layers of variation: the biological differences between mice, and the sampling of reads from each library.</p>
<p>The Poisson distribution describes only the second layer. If a library contains a gene at an expected count of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>μ</mi><annotation encoding="application/x-tex">\mu</annotation></semantics></math>, the count has variance <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>μ</mi><annotation encoding="application/x-tex">\mu</annotation></semantics></math>. That is a good model for technical replicates, the same library sequenced on several lanes (Marioni et al.&nbsp;2008), but not for biological ones.</p>
<p>The negative binomial distribution adds the first layer. Its variance is <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>+</mo><mi>ϕ</mi><msup><mi>μ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\mu + \phi \mu^2</annotation></semantics></math>, where <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>ϕ</mi><annotation encoding="application/x-tex">\phi</annotation></semantics></math> is the dispersion: the squared coefficient of variation of the true expression between replicates. This is the model behind edgeR (Robinson, McCarthy and Smyth 2010; McCarthy, Chen and Smyth 2012) and DESeq2 (Love, Huber and Anders 2014). The ratio of the two variances is <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>+</mo><mi>ϕ</mi><mi>μ</mi></mrow><annotation encoding="application/x-tex">1 + \phi \mu</annotation></semantics></math>, so the gap grows with expression. For a gene with a modest dispersion of 0.05 and a mean count of 150, the real variance is 8.5 times the Poisson variance.</p>
</section>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>Each gene gets a baseline mean count between a few reads and several thousand, and a dispersion that falls with expression and scatters between genes. There are 4 biological replicates per condition, and 10% of the 3,000 genes truly change by a factor of two, up or down. The rest are null. Sequencing depth differs between samples.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">n_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3000</span></span>
<span id="cb2-2">n_per <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>                                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># biological replicates per condition</span></span>
<span id="cb2-3">de_frac <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.10</span></span>
<span id="cb2-4">group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n_per))</span>
<span id="cb2-5">is_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> de_frac <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_genes</span>
<span id="cb2-6"></span>
<span id="cb2-7">simulate_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb2-8">  mu0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.2</span>))       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline mean count per gene</span></span>
<span id="cb2-9">  phi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> mu0) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NB dispersion, gene to gene scatter</span></span>
<span id="cb2-10">  lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(is_de, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), n_genes, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log2 fold change</span></span>
<span id="cb2-11">  depth <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sequencing depth per sample</span></span>
<span id="cb2-12">  mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(mu0, depth) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(lfc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>))</span>
<span id="cb2-13">  counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(mu), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_genes)</span>
<span id="cb2-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">storage.mode</span>(counts) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"integer"</span></span>
<span id="cb2-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gene"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes))</span>
<span id="cb2-16">  counts</span>
<span id="cb2-17">}</span>
<span id="cb2-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb2-19">counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>()</span>
<span id="cb2-20"></span>
<span id="cb2-21">phi_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb2-22">mu_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span></span>
<span id="cb2-23">ratio_example <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> phi_example <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mu_example</span></code></pre></div></div>
</div>
<p>All four analyses below start from the same filtered table: the edgeR recipe of <code>filterByExpr()</code> to drop genes with too few reads to test, then <code>normLibSizes()</code> for TMM normalisation. The Poisson, quasi-Poisson and edgeR fits use the same normalised library sizes as offsets (an offset is a per-sample adjustment for sequencing depth that the model takes as given), so between them only the variance differs. DESeq2 runs its standard workflow on the same genes and estimates its own size factors, and it tests with a Wald test rather than a likelihood ratio or F test.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb3-2">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb3-3">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, design)</span>
<span id="cb3-4">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb3-5">is_de_k <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> is_de[keep]</span>
<span id="cb3-6">lib <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getNormLibSizes</span>(y)                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># library size x TMM factor</span></span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Poisson and quasi-Poisson GLM, one per gene (closed form, checked against glm() below)</span></span>
<span id="cb3-9">pt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pois_tests</span>(y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, group, lib)</span>
<span id="cb3-10"></span>
<span id="cb3-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR quasi-likelihood pipeline: negative binomial GLM + empirical Bayes QL dispersion</span></span>
<span id="cb3-12">fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb3-13">p_ql <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue</span>
<span id="cb3-14"></span>
<span id="cb3-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2 standard workflow on the same genes</span></span>
<span id="cb3-16">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb3-17">p_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue</span>
<span id="cb3-18"></span>
<span id="cb3-19">s_pois <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_pois, is_de_k)</span>
<span id="cb3-20">s_qp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_qp, is_de_k)</span>
<span id="cb3-21">s_ql <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_ql, is_de_k)</span>
<span id="cb3-22">s_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_deseq, is_de_k)</span>
<span id="cb3-23">n_kept <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(keep)</span>
<span id="cb3-24">df_prior <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fit<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df.prior</span>
<span id="cb3-25">df_gene <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(design)</span>
<span id="cb3-26">crit_known <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qchisq</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 5% cut-off with the variance known</span></span>
<span id="cb3-27">crit_qp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qf</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, df_gene)                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># quasi-Poisson: variance from df_gene df</span></span>
<span id="cb3-28">crit_ql <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qf</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, df_gene <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> df_prior)        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR QL: plus the prior df</span></span></code></pre></div></div>
</div>
<p>A loop of <code>glm()</code> calls, one per gene, is how most people would write the Poisson test, and it is slow for thousands of genes. With two groups and a log link (the model works on the log of the expected count) the fitted values have a closed form, a direct formula with no iterative fitting, so the helper <code>pois_tests()</code> in the setup chunk computes the same likelihood ratio tests for all genes at once. The next chunk checks it against <code>glm()</code> and <code>anova()</code> on the first 200 genes.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">n_check <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span></span>
<span id="cb4-2">off <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(lib)</span>
<span id="cb4-3">p_glm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_check), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) {</span>
<span id="cb4-4">  k <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts[i, ]</span>
<span id="cb4-5">  f_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glm</span>(k <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">offset</span>(off), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> poisson)</span>
<span id="cb4-6">  f_q <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glm</span>(k <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">offset</span>(off), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> quasipoisson)</span>
<span id="cb4-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">anova</span>(f_p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chisq"</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pr(&gt;Chi)"</span>], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">anova</span>(f_q, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"F"</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pr(&gt;F)"</span>])</span>
<span id="cb4-8">}))</span>
<span id="cb4-9">max_diff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(p_glm <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(pt[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_check), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p_pois"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p_qp"</span>)])))</span>
<span id="cb4-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(max_diff <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>)</span></code></pre></div></div>
</div>
<p>Across those genes the largest difference in p-value between the two routes is 6.6e-06.</p>
</section>
<section id="what-the-poisson-test-does-to-null-genes" class="level2">
<h2 class="anchored" data-anchor-id="what-the-poisson-test-does-to-null-genes">What the Poisson test does to null genes</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb5-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quasi-Poisson GLM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR QL (negative binomial)"</span>,</span>
<span id="cb5-3">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2 (negative binomial)"</span>),</span>
<span id="cb5-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">null genes with p &lt; 0.05</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(s_pois, s_qp, s_ql, s_deseq), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>null_p05)),</span>
<span id="cb5-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">calls at 5% FDR</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(s_pois, s_qp, s_ql, s_deseq), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">num</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_call)),</span>
<span id="cb5-6">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false among calls</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(s_pois, s_qp, s_ql, s_deseq), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp)),</span>
<span id="cb5-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">changed genes found</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(s_pois, s_qp, s_ql, s_deseq), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power)),</span>
<span id="cb5-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">check.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb5-9">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(tab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lrrrr"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 26%">
<col style="width: 23%">
<col style="width: 14%">
<col style="width: 16%">
<col style="width: 18%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">model</th>
<th style="text-align: right;">null genes with p &lt; 0.05</th>
<th style="text-align: right;">calls at 5% FDR</th>
<th style="text-align: right;">false among calls</th>
<th style="text-align: right;">changed genes found</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Poisson GLM</td>
<td style="text-align: right;">52.9%</td>
<td style="text-align: right;">1,588</td>
<td style="text-align: right;">81.4%</td>
<td style="text-align: right;">98.7%</td>
</tr>
<tr class="even">
<td style="text-align: left;">quasi-Poisson GLM</td>
<td style="text-align: right;">5.3%</td>
<td style="text-align: right;">98</td>
<td style="text-align: right;">2.0%</td>
<td style="text-align: right;">32.1%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">edgeR QL (negative binomial)</td>
<td style="text-align: right;">5.3%</td>
<td style="text-align: right;">219</td>
<td style="text-align: right;">4.6%</td>
<td style="text-align: right;">69.9%</td>
</tr>
<tr class="even">
<td style="text-align: left;">DESeq2 (negative binomial)</td>
<td style="text-align: right;">5.7%</td>
<td style="text-align: right;">246</td>
<td style="text-align: right;">8.1%</td>
<td style="text-align: right;">75.6%</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The Poisson test calls 1,588 genes at 5% FDR. It finds nearly every changed gene, 98.7% of them, but 81.4% of its calls are false. The model assumes that each count varies only by the sampling of reads, so ordinary differences between mice in the same group look to it like a treatment effect. Both negative binomial tools keep the share of null genes below 0.05 close to the promised 5%. DESeq2’s share of false calls, 8.1%, is a little above 5%, and not only by chance: over 10 further simulated data sets it ranged from 6.5% to 10.0%, against 1.9% to 6.3% for edgeR. The scoring applies the Benjamini-Hochberg adjustment to every method’s raw p-values in the same way, which skips DESeq2’s own independent filtering; comparing the two negative binomial tools is not the subject of this post.</p>
<p>If you drew a histogram of the Poisson p-values, you would see the anti-conservative shape described in <a href="https://pseudocount.com/posts/p-value-histogram-diagnostics/">the post on p-value histograms</a>: a floor that leans towards zero. Storey’s estimate of the null fraction from these p-values is 0.32, against a true value of 0.90.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">norm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (lib <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(lib)))       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># counts scaled to a common depth</span></span>
<span id="cb6-2">gene_mean <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(norm)</span>
<span id="cb6-3">within_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(norm[, group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, var) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(norm[, group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, var)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb6-4">ratio_mv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(within_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> gene_mean)</span>
<span id="cb6-5">phi_mom <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>((within_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> gene_mean) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> gene_mean<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one dispersion for all genes</span></span>
<span id="cb6-6">pi0_pois <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_pois <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Storey's null fraction estimate, Poisson p-values</span></span>
<span id="cb6-7">pi0_true <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de_k)</span>
<span id="cb6-8"></span>
<span id="cb6-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pearson goodness-of-fit: under a Poisson model the statistic follows chi-square on df_gene df</span></span>
<span id="cb6-10">gof_fail <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pchisq</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pearson, df_gene, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb6-11">disp_med <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>disp)</span>
<span id="cb6-12">bins <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(gene_mean, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(gene_mean, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">include.lowest =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb6-13">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bin"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="cb6-14">disp_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>disp, bins, median)</span>
<span id="cb6-15">mean_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(gene_mean, bins, median)</span>
<span id="cb6-16"></span>
<span id="cb6-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># false positive rate among null genes, by expression bin</span></span>
<span id="cb6-18">fpr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quasi-Poisson GLM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR QL"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m) {</span>
<span id="cb6-19">  p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">switch</span>(m, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_pois, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quasi-Poisson GLM"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_qp,</span>
<span id="cb6-20">              <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR QL"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> p_ql, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> p_deseq)</span>
<span id="cb6-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bin =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(bins), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(mean_bin),</span>
<span id="cb6-22">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fpr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(p[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de_k] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, bins[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de_k], mean)))</span>
<span id="cb6-23">}))</span>
<span id="cb6-24">fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quasi-Poisson GLM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR QL"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>))</span>
<span id="cb6-25">fpr_pois_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fpr[fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span>][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb6-26">fpr_pois_high <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fpr[fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span>][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">panels <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"All four models"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Without Poisson, zoomed"</span>)</span>
<span id="cb7-2">fpr_plot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform</span>(fpr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(panels[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], panels)),</span>
<span id="cb7-3">                  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform</span>(fpr[fpr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span>, ], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(panels[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], panels)))</span>
<span id="cb7-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(fpr_plot, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(mean, fpr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> model)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey50"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> panel, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scales =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"free_y"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_log10</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand_limits</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quasi-Poisson GLM"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8799"</span>,</span>
<span id="cb7-12">                                 <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR QL"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f2c3d"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_shape_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson GLM"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quasi-Poisson GLM"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span>,</span>
<span id="cb7-14">                                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR QL"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"median normalised count in bin (log scale)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null genes with p &lt; 0.05"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-16">  theme_pc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">strip.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-fpr" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two line charts with mean count on a log x axis and the share of null genes with p below 0.05 on the y axis. Left, all four models: the Poisson line starts well above the dashed 5% line for the lowest-expressed genes and climbs steeply with expression, while the other three lines lie flat along the dashed line. Right, zoomed on quasi-Poisson, edgeR and DESeq2: the three lines wander a little above and below the dashed 5% line with no trend in expression.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-fpr-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/poisson-vs-negative-binomial/index_files/figure-html/fig-fpr-1.png" class="img-fluid figure-img" alt="Two line charts with mean count on a log x axis and the share of null genes with p below 0.05 on the y axis. Left, all four models: the Poisson line starts well above the dashed 5% line for the lowest-expressed genes and climbs steeply with expression, while the other three lines lie flat along the dashed line. Right, zoomed on quasi-Poisson, edgeR and DESeq2: the three lines wander a little above and below the dashed 5% line with no trend in expression." width="816">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-fpr-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Share of null genes with p &lt; 0.05, by expression. Each point is one fifth of the genes, placed at its median normalised count. The dashed line is the 5% that a valid test should give. The right panel leaves out the Poisson model and zooms in on the other three.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The damage grows with expression, as the variance ratio <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>+</mo><mi>ϕ</mi><mi>μ</mi></mrow><annotation encoding="application/x-tex">1 + \phi \mu</annotation></semantics></math> predicts. Among the fifth of genes with the lowest counts (median normalised count 34) the Poisson test already gives p &lt; 0.05 for 30.6% of null genes; in the top fifth (median 720) it reaches 78.1%. Dropping weakly expressed genes therefore does nothing to rescue a Poisson analysis: the genes that remain are the ones where the assumption is furthest off. The other three models stay near the dashed line in every bin.</p>
</section>
<section id="diagnostic-1-the-mean-variance-plot" class="level2">
<h2 class="anchored" data-anchor-id="diagnostic-1-the-mean-variance-plot">Diagnostic 1: the mean-variance plot</h2>
<p>Variance larger than the mean is called overdispersion, and it is what both diagnostics below measure.</p>
<p>You cannot see the truth in real data, but you can see the variance. The first check needs no model. For each gene, scale the counts to a common sequencing depth, compute the mean across samples and the variance within each condition, and plot one against the other on log scales. The variance is taken within conditions and averaged, so that a real treatment effect does not inflate it.</p>
<p>Under a Poisson model the points would scatter around the diagonal where variance equals mean. Here the median ratio of variance to mean is 7.9, and the cloud pulls away from the diagonal as the mean rises. The violet curve is the negative binomial variance <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>+</mo><mi>ϕ</mi><msup><mi>μ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\mu + \phi \mu^2</annotation></semantics></math> with a single dispersion for all genes, <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>ϕ</mi><annotation encoding="application/x-tex">\phi</annotation></semantics></math> = 0.047, taken as the median over genes of (variance minus mean) divided by the squared mean. It follows the cloud; the diagonal does not.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">mv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> gene_mean, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var =</span> within_var)</span>
<span id="cb8-2">grid_m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log10</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(gene_mean)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log10</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(gene_mean)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span>
<span id="cb8-3">nb_curve <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> grid_m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var =</span> grid_m <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> phi_mom <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> grid_m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb8-4">comma <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trim =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb8-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(mv, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(mean, var)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#6b6980"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">slope =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">intercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> nb_curve, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> comma) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> comma) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean normalised count (log scale)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"within-group variance (log scale)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-11">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-meanvar" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Scatter plot of several thousand grey points on log-log axes. The lowest-expressed genes sit close to a dashed diagonal line where variance equals mean; as the mean grows the cloud rises more steeply than that line, following a violet curve, and ends more than two orders of magnitude above it for the most highly expressed genes.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-meanvar-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/poisson-vs-negative-binomial/index_files/figure-html/fig-meanvar-1.png" class="img-fluid figure-img" alt="Scatter plot of several thousand grey points on log-log axes. The lowest-expressed genes sit close to a dashed diagonal line where variance equals mean; as the mean grows the cloud rises more steeply than that line, following a violet curve, and ends more than two orders of magnitude above it for the most highly expressed genes." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-meanvar-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Mean against within-group variance for every gene, both on log scales. The magenta dashed line is what a Poisson model assumes (variance equal to the mean); the violet curve is a negative binomial variance with one dispersion for all genes.
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="diagnostic-2-the-pearson-dispersion-statistic" class="level2">
<h2 class="anchored" data-anchor-id="diagnostic-2-the-pearson-dispersion-statistic">Diagnostic 2: the Pearson dispersion statistic</h2>
<p>The second check uses the Poisson fit itself. For each gene, sum the squared Pearson residuals, (observed minus fitted) squared divided by fitted, over the samples, and divide the sum by the residual degrees of freedom: 8 samples minus 2 fitted means leaves 6. This is the Pearson dispersion statistic. If the Poisson model were right, it would scatter around 1, and the sum would follow a chi-square distribution on 6 degrees of freedom.</p>
<p>Here the median statistic is 7.7, and 88.1% of genes fail the chi-square goodness-of-fit test at the 5% level, where about 5% would fail under a Poisson model. The statistic estimates the variance ratio <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>+</mo><mi>ϕ</mi><mi>μ</mi></mrow><annotation encoding="application/x-tex">1 + \phi \mu</annotation></semantics></math>, so it also rises with the mean: its median is 2.7 in the lowest fifth of genes and 33.8 in the highest.</p>
<p>You do not need the closed-form helper to get this number for a single gene. It is what <code>summary()</code> of a <code>glm()</code> fit with <code>family = quasipoisson</code> prints as the dispersion parameter: base R’s <code>summary.glm()</code> estimates it as the sum of squared Pearson residuals divided by the residual degrees of freedom.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> gene_mean, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>disp), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(mean, disp)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#6b6980"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> comma) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> comma) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean normalised count (log scale)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pearson dispersion (log scale)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-6">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-pearson" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Scatter plot of grey points with mean count on a log x axis and Pearson dispersion on a log y axis. The lowest-count genes run from about 0.3 to about 5, mostly above the dashed line at 1; the cloud rises steadily with the mean and reaches values in the tens and hundreds for the most highly expressed genes.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-pearson-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/poisson-vs-negative-binomial/index_files/figure-html/fig-pearson-1.png" class="img-fluid figure-img" alt="Scatter plot of grey points with mean count on a log x axis and Pearson dispersion on a log y axis. The lowest-count genes run from about 0.3 to about 5, mostly above the dashed line at 1; the cloud rises steadily with the mean and reaches values in the tens and hundreds for the most highly expressed genes." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-pearson-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: The Pearson dispersion statistic from the Poisson fit of each gene, against its mean count. A Poisson model expects values scattered around 1 (dashed line).
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="quasi-poisson-right-error-rate-wrong-power" class="level2">
<h2 class="anchored" data-anchor-id="quasi-poisson-right-error-rate-wrong-power">Quasi-Poisson: right error rate, wrong power</h2>
<p>The quasi-Poisson model is the usual textbook answer to overdispersion when the software at hand only offers a Poisson model. It keeps the Poisson mean but lets the variance be a multiple of it, <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mi>μ</mi></mrow><annotation encoding="application/x-tex">\theta \mu</annotation></semantics></math>, with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>θ</mi><annotation encoding="application/x-tex">\theta</annotation></semantics></math> estimated for each gene by the Pearson statistic above. Tests divide by <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>θ</mi><annotation encoding="application/x-tex">\theta</annotation></semantics></math> and compare against an F distribution; in R this is <code>glm(family = quasipoisson)</code> followed by <code>anova(fit, test = "F")</code>, which is what <code>pois_tests()</code> reproduces.</p>
<p>In the table, quasi-Poisson gets the error rate right: 5.3% of null genes below 0.05 and 2.0% false among its calls. But it calls only 98 genes and finds 32.1% of the changed ones, against 69.9% for edgeR.</p>
<p>The cost comes from estimating <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>θ</mi><annotation encoding="application/x-tex">\theta</annotation></semantics></math> one gene at a time. With 6 residual degrees of freedom, the estimate is noisy, and the F test pays for that noise with a higher bar. The 5% cut-off for the test statistic is 3.84 when the variance is known and 5.99 on an F distribution with 6 denominator degrees of freedom. edgeR’s quasi-likelihood pipeline also estimates a quasi-dispersion for every gene, on top of the negative binomial variance, but it squeezes those estimates towards a trend fitted across all genes. That empirical Bayes step is worth 11.8 extra degrees of freedom here (prior degrees of freedom: the information borrowed from the other genes, counted as if it were extra replicates), and the cut-off drops to roughly 4.42.</p>
<p>To check that this is the reason, the next chunk applies the same kind of squeezing to the quasi-Poisson dispersions with limma’s <code>squeezeVar()</code>, using the log of the mean count as the trend covariate, and repeats the F test with the pooled degrees of freedom.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">sq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> limma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">squeezeVar</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>disp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> df_gene, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covariate =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(gene_mean))</span>
<span id="cb10-2">p_qp_shared <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pf</span>(pt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lr <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> sq<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>var.post, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, df_gene <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> sq<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df.prior, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb10-3">s_qp_shared <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_qp_shared, is_de_k)</span>
<span id="cb10-4">df_prior_qp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sq<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df.prior</span></code></pre></div></div>
</div>
<p>With the shared dispersion, quasi-Poisson gains 13.4 prior degrees of freedom, keeps 5.7% of null genes below 0.05, and finds 70.6% of the changed genes, close to edgeR. So the quasi-Poisson model is not badly calibrated; it is wasteful, because it treats each gene as if the other few thousand had nothing to say about its variance. It also assumes that the variance is proportional to the mean within a gene, which is off when the two conditions differ a lot in expression; in this simulation that mattered much less than the degrees of freedom.</p>
<p>One data set can flatter or punish the quasi-Poisson test, because with so few calls the Benjamini-Hochberg cut-off moves a lot. The next chunk repeats the whole simulation 10 more times with new seeds and keeps only the share of changed genes found.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">n_rep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb11-2">rep_runs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_rep), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(seed) {</span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(seed)</span>
<span id="cb11-4">  cnt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>()</span>
<span id="cb11-5">  yr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(cnt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb11-6">  kr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(yr, design)</span>
<span id="cb11-7">  yr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(yr[kr, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb11-8">  de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> is_de[kr]</span>
<span id="cb11-9">  libr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getNormLibSizes</span>(yr)</span>
<span id="cb11-10">  ptr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pois_tests</span>(yr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, group, libr)</span>
<span id="cb11-11">  gm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(yr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (libr <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(libr))))</span>
<span id="cb11-12">  sqr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> limma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">squeezeVar</span>(ptr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>disp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> df_gene, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">covariate =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(gm))</span>
<span id="cb11-13">  p_sh <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pf</span>(ptr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lr <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> sqr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>var.post, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, df_gene <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> sqr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df.prior, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb11-14">  p_q <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(yr, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue</span>
<span id="cb11-15">  ddr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(yr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb11-16">  p_d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(ddr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue</span>
<span id="cb11-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pow_qp =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(ptr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_qp, de)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pow_shared =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_sh, de)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power,</span>
<span id="cb11-18">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pow_ql =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_q, de)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_ql =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_q, de)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp,</span>
<span id="cb11-19">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_deseq =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_d, de)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp)</span>
<span id="cb11-20">}))</span>
<span id="cb11-21">qp_share <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> rep_runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pow_qp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> rep_runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pow_ql     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># quasi-Poisson power as a share of edgeR's</span></span></code></pre></div></div>
</div>
<p>Across those runs, quasi-Poisson found 6.1% to 25.1% of the changed genes (mean 18.6%), edgeR 64.4% to 71.6% (mean 69.1%), and quasi-Poisson with the shared dispersion 64.4% to 73.1%. So the data set above is on the kind side for quasi-Poisson: on average it finds 27% of what edgeR finds, and at best 37% of it.</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>For RNA-seq counts with biological replicates, use a negative binomial model that shares dispersion information across genes. That is what edgeR and DESeq2 are for, and in their standard workflows they need no tuning for this. The edgeR quasi-likelihood version used above:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb12-2">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb12-3">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, design)</span>
<span id="cb12-4">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb12-5">fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb12-6">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb12-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">topTags</span>(res)</span></code></pre></div></div>
</div>
<p><code>legacy = FALSE</code> switches on the newer quasi-dispersion method introduced in edgeR 4.0. It estimates one common negative binomial dispersion itself, from the most highly expressed genes, so no separate <code>estimateDisp()</code> call is needed. The default in edgeR 4.0 is still <code>legacy = TRUE</code>, which stops with an error unless <code>estimateDisp()</code> has been run first; writing <code>legacy = FALSE</code> out gives the same method whichever edgeR version you run.</p>
<p>If you have inherited a per-gene Poisson analysis, from a general statistics package or a loop of <code>glm()</code> calls, run the Pearson check before trusting any of it. The helper <code>pois_tests()</code> has to be copied from the setup chunk, and its closed form handles one grouping factor only:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">pt_check <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pois_tests</span>(y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getNormLibSizes</span>(y))</span>
<span id="cb13-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(pt_check<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>disp)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  0.3133   3.5317   7.7152  18.1498  17.8413 584.7593 </code></pre>
</div>
</div>
<p>For any other design, fit one gene at a time and read the same number from <code>glm()</code>, where <code>k</code> is the gene’s counts and <code>lib</code> the normalised library sizes:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glm</span>(k <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">offset</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(lib)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> quasipoisson))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dispersion</span></code></pre></div></div>
</div>
<p>Values scattered around 1 across the whole range of expression would mean the Poisson model is adequate, as it is for technical replicates of one library. Values well above 1 that rise with the mean, as here, mean the Poisson p-values are too small, and a gene list built on them will contain many false calls, as in the table above. If a general GLM tool is all you have, quasi-Poisson is the minimum repair: it controls the error rate, but with a handful of replicates it throws away much of the power that a shared dispersion estimate would give you.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Marioni JC, Mason CE, Mane SM et al.&nbsp;2008 Genome Research 18(9):1509-1517 (<a href="https://doi.org/10.1101/gr.079558.108">doi:10.1101/gr.079558.108</a>)</li>
<li>Robinson MD, McCarthy DJ, Smyth GK 2010 Bioinformatics 26(1):139-140 (<a href="https://doi.org/10.1093/bioinformatics/btp616">doi:10.1093/bioinformatics/btp616</a>)</li>
<li>McCarthy DJ, Chen Y, Smyth GK 2012 Nucleic Acids Research 40(10):4288-4297 (<a href="https://doi.org/10.1093/nar/gks042">doi:10.1093/nar/gks042</a>)</li>
<li>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, edgeR 4.8.2,
generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0,
limma 3.66.0, MatrixGenerics 1.22.0, matrixStats 1.5.0, S4Vectors
0.48.1, Seqinfo 1.0.0, SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>RNA-seq</category>
  <category>count models</category>
  <category>edgeR</category>
  <category>DESeq2</category>
  <category>diagnostics</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/poisson-vs-negative-binomial/</guid>
  <pubDate>Thu, 24 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/poisson-vs-negative-binomial/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Why correlations of relative abundances mislead</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/correlation-of-proportions/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2))</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4"</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># linewidth aesthetic</span></span>
<span id="cb1-3">f2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, x)</span>
<span id="cb1-4">f3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.3f"</span>, x)</span>
<span id="cb1-5">pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.*f%%"</span>, d, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-6">int <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb1-7">num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">drop0trailing =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># plain decimal as a string</span></span>
<span id="cb1-8">violet <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>; magenta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>; grey <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8797"</span></span>
<span id="cb1-9">theme_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>),</span>
<span id="cb1-11">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
</details>
</div>
<p>You have a table of relative abundances, bacterial taxa from 16S sequencing or cell types from a single-cell atlas, and you want to know which ones go together. The obvious move is <code>cor()</code> on the proportions, followed by a network of the strongest pairs. The question is whether a correlation between two proportions says anything about the two organisms or cell types themselves.</p>
<p>Often it does not. Proportions are shares of a total, and shares are tied to each other whatever the biology does. In the simulation below, 30 taxa have absolute abundances that are completely independent of each other. Yet 11.1% of taxon pairs show a correlation of proportions with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math>, where a correct test gives 5% (the absolute abundances give 5.2%). The most abundant taxon is negatively correlated with 95% of the others, with a median correlation of -0.22. Here, taking logs of the proportions makes it worse, not better.</p>
<section id="why-proportions-cannot-be-independent" class="level2">
<h2 class="anchored" data-anchor-id="why-proportions-cannot-be-independent">Why proportions cannot be independent</h2>
<p>In every sample the proportions add up to 1. A quantity that never varies has zero covariance with anything, so for any part <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>i</mi><annotation encoding="application/x-tex">i</annotation></semantics></math> the covariance of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>p</mi><mi>i</mi></msub><annotation encoding="application/x-tex">p_i</annotation></semantics></math> with the total is zero, and splitting the total into its parts gives</p>
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><munder><mo>∑</mo><mrow><mi>j</mi><mo>≠</mo><mi>i</mi></mrow></munder><mrow><mi mathvariant="normal">cov</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><msub><mi>p</mi><mi>i</mi></msub><mo>,</mo><msub><mi>p</mi><mi>j</mi></msub><mo stretchy="false" form="postfix">)</mo><mo>=</mo><mi>−</mi><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><msub><mi>p</mi><mi>i</mi></msub><mo stretchy="false" form="postfix">)</mo><mi>.</mi></mrow><annotation encoding="application/x-tex">
\sum_{j \neq i} \operatorname{cov}(p_i, p_j) = -\operatorname{var}(p_i).
</annotation></semantics></math></p>
<p>Each part’s covariances with the others must add up to minus its own variance. That is an identity, not an estimate: if one part goes up, the others must, taken together, go down by the same amount. So the correlations of proportions cannot all be zero even when the underlying abundances have nothing to do with each other. Data with this property are called <em>compositional</em>, and dividing by the total is called <em>closure</em>.</p>
<p>Sequencing makes almost every abundance table compositional. The number of reads per sample is set by the sequencer, not by how many cells were in the tube, so only the relative amounts carry information. Gloor et al.&nbsp;(2017) make this case for microbiome data. The same applies to cell-type proportions from single-cell data, where the total is the number of cells captured.</p>
</section>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">clr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(x) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(x))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># rows = samples, columns = parts</span></span>
<span id="cb2-2">rho <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(z) {                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># z: CLR-transformed matrix</span></span>
<span id="cb2-3">  v <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(z, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var)</span>
<span id="cb2-4">  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cov</span>(z) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(v, v, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"+"</span>)                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># = 1 - var(z_i - z_j) / (var z_i + var z_j)</span></span>
<span id="cb2-5">}</span>
<span id="cb2-6">lr_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) {                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># variance of log(x_i / x_j), all pairs</span></span>
<span id="cb2-7">  l <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(x); v <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(l, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var)</span>
<span id="cb2-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(v, v, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"+"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cov</span>(l)</span>
<span id="cb2-9">}</span>
<span id="cb2-10">pairs_of <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m) m[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">upper.tri</span>(m)]         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one value per pair</span></span>
<span id="cb2-11">cor_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(r, n) {                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># two-sided p-value of the usual t test</span></span>
<span id="cb2-12">  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pt</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(r <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>((n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> r<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))), n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb2-13">}</span></code></pre></div></div>
</div>
<p>Each simulated data set has 50 samples and 30 taxa. The absolute abundance of every taxon in every sample is drawn independently from a log-normal distribution with a standard deviation of 1 on the natural log scale, so the true correlation between any two taxa is zero. The taxa differ in typical size along a steep curve (a Zipf curve with exponent 1.5, so the typical size of the <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>k</mi><annotation encoding="application/x-tex">k</annotation></semantics></math>-th largest taxon falls as <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>k</mi><annotation encoding="application/x-tex">k</annotation></semantics></math> to the power -1.5), and on average the largest one holds 37% of each sample. Each sample is then sequenced: a number of reads between 5,000 and 50,000 is drawn from the true proportions. Only 0.2% of the resulting counts are zero.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">n_samples <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>; n_taxa <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>; sd_log <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>; zipf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span></span>
<span id="cb3-2">depth_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50000</span>); pc_main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span></span>
<span id="cb3-3"></span>
<span id="cb3-4">zipf_shares <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(D, a) { s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(D)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^-</span>a; s <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(s) }</span>
<span id="cb3-5"></span>
<span id="cb3-6">simulate_community <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(shares, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> n_samples, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">depth =</span> depth_range) {</span>
<span id="cb3-7">  D <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(shares)</span>
<span id="cb3-8">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># absolute abundances: independent log-normal, one column per taxon</span></span>
<span id="cb3-9">  A <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> D, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(shares), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> sd_log), n, D))</span>
<span id="cb3-10">  P <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> A <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(A)                                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true proportions</span></span>
<span id="cb3-11">  reads <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(depth[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(depth[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]))))</span>
<span id="cb3-12">  Y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rmultinom</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, reads[i], P[i, ])[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(D)))</span>
<span id="cb3-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">A =</span> A, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">P =</span> P, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Y =</span> Y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">reads =</span> reads)</span>
<span id="cb3-14">}</span></code></pre></div></div>
</div>
<p>Three assumptions matter. Independence of the absolute abundances is the truth being tested, so any correlation that comes out is spurious. Every taxon has the same variance on the log scale; this makes the arithmetic further down exact, and real taxa vary in variability. And one taxon dominates, which the next sections vary on purpose.</p>
<p>The analysis is repeated on 200 data sets, giving 87,000 pairwise correlations. The <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>p</mi><annotation encoding="application/x-tex">p</annotation></semantics></math>-values come from the same <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>t</mi><annotation encoding="application/x-tex">t</annotation></semantics></math> test that <code>cor.test()</code> uses; the code checks the two agree.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">n_sets <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span></span>
<span id="cb4-2">shares_main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zipf_shares</span>(n_taxa, zipf)</span>
<span id="cb4-3">is_dom <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, n_taxa, n_taxa); is_dom[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, ] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> is_dom[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb4-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260922</span>)</span>
<span id="cb4-5">main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_sets), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) {</span>
<span id="cb4-6">  s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_community</span>(shares_main)</span>
<span id="cb4-7">  props <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y)                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># observed relative abundance</span></span>
<span id="cb4-8">  z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc_main)</span>
<span id="cb4-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">set =</span> k, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dominant =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(is_dom),</span>
<span id="cb4-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">absolute =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>A))),</span>
<span id="cb4-11">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(props)),</span>
<span id="cb4-12">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log_proportion =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>((s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc_main) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc_main)))),</span>
<span id="cb4-13">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(z)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(z)),</span>
<span id="cb4-14">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top_share =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(props[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zero_frac =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))</span>
<span id="cb4-15">}))</span>
<span id="cb4-16">n_pairs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">choose</span>(n_taxa, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb4-17">p_of <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(r) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor_p</span>(r, n_samples)</span>
<span id="cb4-18">fp_abs  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>absolute) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-19">fp_prop <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-20">fp_logp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log_proportion) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-21">fp_clr  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-22">fp_prop_dom <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion[main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-23">fp_prop_oth <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-24">med_dom_prop <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion[main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant])</span>
<span id="cb4-25">med_oth_prop <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant])</span>
<span id="cb4-26">dom_neg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion[main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb4-27">oth_pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb4-28">med_oth_logp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log_proportion[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant])</span>
<span id="cb4-29">mean_abs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>absolute); mean_clr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr); mean_rho <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho)</span>
<span id="cb4-30">med_dom_clr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr[main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant])</span>
<span id="cb4-31">top_share_main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>top_share); zero_main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>zero_frac)</span>
<span id="cb4-32">theory_main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (n_taxa <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb5-2">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rlnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>); y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x; w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rlnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>); u <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rlnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>)</span>
<span id="cb5-3">toy_abs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(x, y, w, u)                    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># y is exactly proportional to x</span></span>
<span id="cb5-4">toy_rel <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> toy_abs <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(toy_abs)           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the same data as proportions</span></span>
<span id="cb5-5">z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(toy_rel)</span>
<span id="cb5-6">rho_def <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(z[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> z[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"w"</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(z[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(z[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"w"</span>]))</span>
<span id="cb5-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(</span>
<span id="cb5-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all.equal</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(toy_abs))[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># proportional pair: rho = 1 ...</span></span>
<span id="cb5-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all.equal</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(z)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... before and after closure</span></span>
<span id="cb5-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all.equal</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(z)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"w"</span>], rho_def)),          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># matrix form = definition</span></span>
<span id="cb5-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all.equal</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lr_var</span>(toy_abs), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lr_var</span>(toy_rel))),   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log-ratio variance ignores closure</span></span>
<span id="cb5-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all.equal</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor_p</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(toy_rel[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>], toy_rel[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"w"</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>),</span>
<span id="cb5-13">                   <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor.test</span>(toy_rel[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>], toy_rel[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"w"</span>])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value)))</span>
<span id="cb5-14"></span>
<span id="cb5-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a straight line on the log scale that is not proportionality: y = x^2, plus 9 other parts</span></span>
<span id="cb5-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb5-17">x2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rlnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>)</span>
<span id="cb5-18">toy_sq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> x2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rlnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>))</span>
<span id="cb5-19">z_sq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(toy_sq)</span>
<span id="cb5-20">cor_sq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(z_sq[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>], z_sq[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>]); rho_sq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(z_sq)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>]</span>
<span id="cb5-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(rho_sq <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> cor_sq)</span></code></pre></div></div>
</div>
</section>
<section id="correlations-of-proportions-under-independence" class="level2">
<h2 class="anchored" data-anchor-id="correlations-of-proportions-under-independence">Correlations of proportions under independence</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">absolute =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log absolute abundance"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportion"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CLR"</span>)</span>
<span id="cb6-2">hist_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(lab), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m)</span>
<span id="cb6-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(lab[m]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> lab), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> main[[m]],</span>
<span id="cb6-4">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pair =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(main<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dominant, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with the dominant taxon"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other pairs"</span>))))</span>
<span id="cb6-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(hist_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(r, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">after_stat</span>(density), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> pair)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">binwidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">boundary =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identity"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_vline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> method) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with the dominant taxon"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other pairs"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet),</span>
<span id="cb6-10">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pearson correlation across samples"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"density"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-12">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-hist" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three histogram panels. For log absolute abundance both groups of pairs are centred on zero. For proportions the pairs with the dominant taxon sit well below zero and the other pairs sit slightly above zero. For CLR values both groups are centred just below zero and overlap.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-hist-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/correlation-of-proportions/index_files/figure-html/fig-hist-1.png" class="img-fluid figure-img" alt="Three histogram panels. For log absolute abundance both groups of pairs are centred on zero. For proportions the pairs with the dominant taxon sit well below zero and the other pairs sit slightly above zero. For CLR values both groups are centred just below zero and overlap." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-hist-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Pairwise correlations between taxa whose absolute abundances are independent, pooled over all simulated data sets. Pairs that include the dominant taxon are shown separately from all other pairs; each histogram is scaled to unit area.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The left panel is the truth: correlations of the log absolute abundances scatter around zero (mean -0.001), and 5.2% of pairs reach <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math>, as they should. The middle panel is what <code>cor()</code> on the proportions reports for the same samples. It is not one distribution but two. The pairs that include the dominant taxon are pushed down, to a median of -0.22, and 31% of them are “significant”. The other pairs are pushed slightly up, to a median of 0.05, and 9.7% of them pass <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math>. A network built from these correlations would put the dominant taxon at the centre of a star of negative edges, which looks like competition or exclusion and is purely arithmetic.</p>
<p>Spurious correlations of proportions are not always negative: here 63% of the pairs without the dominant taxon are positive. The identity only fixes the sum of each part’s covariances, and for a minor taxon the covariance with the dominant one more than covers it, leaving room for positive covariances with the other minor taxa.</p>
</section>
<section id="a-shared-denominator" class="level2">
<h2 class="anchored" data-anchor-id="a-shared-denominator">A shared denominator</h2>
<p>The positive side has an old explanation. The proportion of taxon <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>i</mi><annotation encoding="application/x-tex">i</annotation></semantics></math> is its abundance divided by the total, and the total is the same for every taxon in that sample. Two ratios with a common denominator are correlated even when their numerators are independent: when the denominator happens to be large, both ratios are small. Pearson (1897) described this “spurious correlation” for indices used in measuring organs, where one measurement is divided by another. When one taxon dominates, a large part of the total is that taxon, so every other proportion is roughly an independent abundance divided by the dominant one. They rise and fall together, and the dominant taxon moves against them.</p>
<p>Logs do not help, because <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">log</mi><mo rspace="0.1667em">⁡</mo></mrow><msub><mi>p</mi><mi>i</mi></msub><mo>=</mo><mrow><mi mathvariant="normal">log</mi><mo rspace="0.1667em">⁡</mo></mrow><msub><mi>a</mi><mi>i</mi></msub><mo>−</mo><mrow><mi mathvariant="normal">log</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">\log p_i = \log a_i - \log T</annotation></semantics></math> still contains the shared total <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>T</mi><annotation encoding="application/x-tex">T</annotation></semantics></math>. With log proportions (a pseudocount of 0.5 for the few zeros) the other pairs have a median correlation of 0.15 and 19.1% of all pairs pass <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">zipf_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>)</span>
<span id="cb7-2">n_sets_sweep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb7-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260923</span>)</span>
<span id="cb7-4">sweep_dom <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(zipf_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(a) {</span>
<span id="cb7-5">  sh <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zipf_shares</span>(n_taxa, a)</span>
<span id="cb7-6">  r <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(n_sets_sweep, {</span>
<span id="cb7-7">    s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_community</span>(sh)</span>
<span id="cb7-8">    props <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y); cp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(props); cz <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc_main))</span>
<span id="cb7-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(props[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]),</span>
<span id="cb7-10">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prop_dom =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(cp[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prop_oth =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(cp[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])),</span>
<span id="cb7-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr_dom =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(cz[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr_oth =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(cz[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])))</span>
<span id="cb7-12">  })</span>
<span id="cb7-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zipf =</span> a, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(r)))</span>
<span id="cb7-14">}))</span>
<span id="cb7-15">even <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sweep_dom[sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>zipf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, ]</span>
<span id="cb7-16">steep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sweep_dom[sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>zipf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(zipf_grid), ]</span>
<span id="cb7-17">clr_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unlist</span>(sweep_dom[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"clr_dom"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"clr_oth"</span>)]))</span></code></pre></div></div>
</div>
<p>The strength of the effect depends on how dominant the largest taxon is. The next simulation keeps 30 independent taxa and makes the abundance curve steeper step by step, with 100 data sets per step.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">dom_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb8-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>top, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prop_dom, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportion"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with the dominant taxon"</span>),</span>
<span id="cb8-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>top, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prop_oth, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportion"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other pairs"</span>),</span>
<span id="cb8-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>top, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_dom, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CLR"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with the dominant taxon"</span>),</span>
<span id="cb8-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">top =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>top, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_dom<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_oth, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CLR"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pair =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other pairs"</span>))</span>
<span id="cb8-6">dom_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(dom_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportion"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CLR"</span>))</span>
<span id="cb8-7">dom_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pair <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(dom_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pair, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with the dominant taxon"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other pairs"</span>))</span>
<span id="cb8-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dom_long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> top, r, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> pair)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> magenta, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CLR =</span> violet), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_linetype_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"with the dominant taxon"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solid"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other pairs"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>),</span>
<span id="cb8-13">                        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average share of the most abundant taxon (%)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean correlation"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-15">  theme_pc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.box =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vertical"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.key.width =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unit</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lines"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-dominance" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with the average share of the most abundant taxon on the x axis and the mean correlation on the y axis. For proportions, the line for pairs with the dominant taxon falls steadily below zero while the line for other pairs rises above zero. Both CLR lines stay flat just below zero.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-dominance-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/correlation-of-proportions/index_files/figure-html/fig-dominance-1.png" class="img-fluid figure-img" alt="Line chart with the average share of the most abundant taxon on the x axis and the mean correlation on the y axis. For proportions, the line for pairs with the dominant taxon falls steadily below zero while the line for other pairs rises above zero. Both CLR lines stay flat just below zero." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-dominance-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Mean correlation under independence as one taxon takes a larger share of the community, for proportions and for CLR values. Solid lines: pairs that include the most abundant taxon; dashed lines: all other pairs. The two CLR lines coincide.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With all taxa the same size (each about 3% of a sample), every pair of proportions has a mean correlation near -0.03. At the steepest curve the largest taxon holds 65%, its mean correlation with the others is -0.29, and the mean among the rest has risen to 0.17. The CLR lines barely move (-0.034 to -0.032), for the reason given next.</p>
</section>
<section id="the-centred-log-ratio" class="level2">
<h2 class="anchored" data-anchor-id="the-centred-log-ratio">The centred log-ratio</h2>
<p>The standard alternative comes from the log-ratio approach to compositional data (Aitchison 1982). The centred log-ratio (CLR) of a part is its log abundance minus the mean log abundance of all parts in that sample, which is the log of its ratio to the geometric mean. Two things follow. Dividing a sample by its total subtracts the same constant from every log, and the centring removes it, so the CLR values of proportions and of absolute abundances are identical. And every part contributes equally to the reference, whatever its size, so no single taxon can control it.</p>
<p>In the main simulation the CLR correlations have a mean of -0.034, the pairs with the dominant taxon have a median of -0.031, and 5.7% of all pairs reach <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math>. That is close to the 5.2% of the absolute abundances, and it is the right-hand panel of the first figure: the two groups of pairs now overlap.</p>
<p>The CLR needs the log of every count, and zeros have no log. The usual fix is to add a pseudocount, here 0.5, which has side effects of its own (<a href="https://pseudocount.com/posts/pseudocount-log-fold-change/">see the post on pseudocounts and fold changes</a>). In the main simulation zeros are rare, so the choice hardly matters. To see when it does, the next check uses a steeper abundance curve and shallower sequencing, and looks at the rarest taxa.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">n_sets_zero <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>; shallow <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span>); pc_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-2">rare <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span></span>
<span id="cb9-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260924</span>)</span>
<span id="cb9-4">zero_runs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(n_sets_zero, {</span>
<span id="cb9-5">  s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_community</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zipf_shares</span>(n_taxa, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">depth =</span> shallow)</span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zero =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y[, rare] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>),</span>
<span id="cb9-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">truth =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>A))[rare, rare])),</span>
<span id="cb9-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(pc_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(pc) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc))[rare, rare]))),</span>
<span id="cb9-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(pc_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(pc) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>reads), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc)[, rare]))))</span>
<span id="cb9-10">})</span>
<span id="cb9-11">zero_res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(zero_runs)</span>
<span id="cb9-12">zero_rare <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> zero_res[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]; zero_truth <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> zero_res[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb9-13">zero_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> zero_res[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]; zero_depth <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> zero_res[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>]   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># per pseudocount</span></span></code></pre></div></div>
</div>
<p>With 500 to 10,000 reads per sample, the 10 rarest taxa are zero in 30% of samples. On the absolute abundances, the CLR correlation among them averages -0.035. From the counts it averages -0.039 with a pseudocount of 0.1, -0.013 with 0.5 and 0.025 with 1. A pseudocount turns every zero into the same value, and zeros are more common in shallow samples, so the larger the pseudocount, the more the rare taxa share a dependence on sequencing depth. Their correlation with log depth averages -0.006, -0.125 and -0.204 for the three pseudocounts. The shift is small here, but the choice changes the answer.</p>
</section>
<section id="what-the-clr-cannot-fix" class="level2">
<h2 class="anchored" data-anchor-id="what-the-clr-cannot-fix">What the CLR cannot fix</h2>
<p>The CLR values of a sample also add up to zero, so the identity from the start applies to them too. With independent parts of equal log-scale variance it gives an exact result: the correlation between any two CLR values is <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>−</mi><mn>1</mn><mi>/</mi><mo stretchy="false" form="prefix">(</mo><mi>D</mi><mo>−</mo><mn>1</mn><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">-1/(D - 1)</annotation></semantics></math> for <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>D</mi><annotation encoding="application/x-tex">D</annotation></semantics></math> parts. With 30 taxa that is -0.034, which is the mean found above. With many parts this is close enough to zero to ignore; with few parts it is not.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">parts_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>)</span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260925</span>)</span>
<span id="cb10-3">sweep_parts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(parts_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(D) {</span>
<span id="cb10-4">  r <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(n_sets_sweep, {</span>
<span id="cb10-5">    s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_community</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> D, D))</span>
<span id="cb10-6">    props <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y); z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc_main)</span>
<span id="cb10-7">    cz <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(z))</span>
<span id="cb10-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(props))), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(cz),</span>
<span id="cb10-9">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(z))), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fp_clr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p_of</span>(cz) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>))</span>
<span id="cb10-10">  })</span>
<span id="cb10-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parts =</span> D, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(r)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">theory =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (D <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb10-12">}))</span>
<span id="cb10-13">sp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(D) sweep_parts[sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> D, ]</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">parts_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb11-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parts =</span> sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>proportion, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportion"</span>),</span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parts =</span> sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CLR"</span>),</span>
<span id="cb11-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parts =</span> sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r =</span> sweep_parts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rho"</span>))</span>
<span id="cb11-5">parts_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(parts_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportion"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CLR"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rho"</span>))</span>
<span id="cb11-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(parts_long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(parts, r, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> method)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> sweep_parts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(parts, theory), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inherit.aes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb11-9">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> method), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stroke =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> parts_grid) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_size_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CLR =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.4</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> magenta, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CLR =</span> violet, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho =</span> grey), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_shape_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">proportion =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">CLR =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of parts (log scale)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean correlation"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-16">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-parts" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with the number of parts on a logarithmic x axis and the mean correlation on the y axis. The points for proportions, CLR and rho lie on top of each other and on a dashed curve that starts at minus one half for three parts and rises towards zero as the number of parts grows.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-parts-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/correlation-of-proportions/index_files/figure-html/fig-parts-1.png" class="img-fluid figure-img" alt="Line chart with the number of parts on a logarithmic x axis and the mean correlation on the y axis. The points for proportions, CLR and rho lie on top of each other and on a dashed curve that starts at minus one half for three parts and rises towards zero as the number of parts grows." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-parts-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Mean correlation under independence against the number of parts in an evenly balanced composition. The dashed curve is minus one over the number of parts minus one.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The simulation uses evenly sized parts, so there is no dominant one, and all three measures land on the curve. A single-cell study that tracks 5 cell types gets a mean CLR correlation of -0.25 between cell types that are independent, and 43% of pairs pass <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math> with 50 samples. With 8 parts it is still 16%; with 3 parts, 96%. Only with a few dozen parts does the rate come down to about 5% (5.5% at 30). These rates depend on the number of samples: with fewer donors fewer pairs reach significance, but the mean correlation stays where it is.</p>
<p>No transformation of the proportions removes this, because the information is not in the data. If five cell types always make up the whole, an increase in one must be matched by a decrease somewhere else, and nothing computed from the shares can say whether that was a real loss of cells or only a smaller slice of the same total.</p>
</section>
<section id="proportionality" class="level2">
<h2 class="anchored" data-anchor-id="proportionality">Proportionality</h2>
<p>The CLR fixes the dominant-part problem but still gives a correlation, and correlation is the wrong question for relative data. Lovell et al.&nbsp;(2015) propose asking instead whether two parts are <em>proportional</em>: whether their ratio stays constant across samples. The natural measure is the variance of the log-ratio, <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">log</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mi>x</mi><mi>/</mi><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">\operatorname{var}(\log(x/y))</annotation></semantics></math>. Because <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">log</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><msub><mi>p</mi><mi>x</mi></msub><mi>/</mi><msub><mi>p</mi><mi>y</mi></msub><mo stretchy="false" form="postfix">)</mo><mo>=</mo><mrow><mi mathvariant="normal">log</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><msub><mi>a</mi><mi>x</mi></msub><mi>/</mi><msub><mi>a</mi><mi>y</mi></msub><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">\log(p_x / p_y) = \log(a_x / a_y)</annotation></semantics></math>, the total cancels, and this variance is the same whether you compute it from absolute abundances, from proportions, or from any subset of the parts.</p>
<p>A log-ratio variance on its own has no fixed scale, so it is usually rescaled. Lovell et al.&nbsp;divide it by the variance of one of the two parts and call the result phi. The symmetric version used here, <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>ρ</mi><annotation encoding="application/x-tex">\rho</annotation></semantics></math> (rho), is the one implemented in the propr R package, computed on CLR values by default (Quinn et al.&nbsp;2017). It divides the log-ratio variance by the sum of the two CLR variances and subtracts the result from 1:</p>
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ρ</mi><mo stretchy="false" form="prefix">(</mo><mi>x</mi><mo>,</mo><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mo>=</mo><mn>1</mn><mo>−</mo><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>x</mi><mo>−</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mspace width="0.167em"></mspace><mi>/</mi><mspace width="0.167em"></mspace><mo stretchy="false" form="prefix">[</mo><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>x</mi><mo stretchy="false" form="postfix">)</mo><mo>+</mo><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mo stretchy="false" form="postfix">]</mo></mrow><annotation encoding="application/x-tex">
\rho(x, y) = 1 - \operatorname{var}(\operatorname{clr} x - \operatorname{clr} y) \,/\, [\operatorname{var}(\operatorname{clr} x) + \operatorname{var}(\operatorname{clr} y)]
</annotation></semantics></math></p>
<p>which is the same as</p>
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ρ</mi><mo stretchy="false" form="prefix">(</mo><mi>x</mi><mo>,</mo><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mo>=</mo><mn>2</mn><mrow><mi mathvariant="normal">cov</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>x</mi><mo>,</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mspace width="0.167em"></mspace><mi>/</mi><mspace width="0.167em"></mspace><mo stretchy="false" form="prefix">[</mo><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>x</mi><mo stretchy="false" form="postfix">)</mo><mo>+</mo><mrow><mi mathvariant="normal">var</mi><mo>⁡</mo></mrow><mo stretchy="false" form="prefix">(</mo><mrow><mi mathvariant="normal">clr</mi><mo rspace="0.1667em">⁡</mo></mrow><mi>y</mi><mo stretchy="false" form="postfix">)</mo><mo stretchy="false" form="postfix">]</mo><mi>.</mi></mrow><annotation encoding="application/x-tex">
\rho(x, y) = 2 \operatorname{cov}(\operatorname{clr} x, \operatorname{clr} y) \,/\, [\operatorname{var}(\operatorname{clr} x) + \operatorname{var}(\operatorname{clr} y)].
</annotation></semantics></math></p>
<p>It is 1 when the two parts are exactly proportional, 0 when the log-ratio varies as much as the two parts together, and it is Lin’s concordance correlation coefficient without the term for a difference in means, so a constant ratio other than 1 still scores 1. The <code>rho()</code> function in the setup code implements it; the check after the main simulation confirms that a pair with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>=</mo><mn>3</mn><mi>x</mi></mrow><annotation encoding="application/x-tex">y = 3x</annotation></semantics></math> gets exactly 1 before and after closure and that the matrix form matches the definition.</p>
<p>Under independence rho behaves like the CLR correlation: a mean of -0.034 in the main simulation, and the same <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>−</mi><mn>1</mn><mi>/</mi><mo stretchy="false" form="prefix">(</mo><mi>D</mi><mo>−</mo><mn>1</mn><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">-1/(D - 1)</annotation></semantics></math> curve in the last figure. So rho is not a test of independence, and it does not rescue a five-part composition. What it adds over a CLR correlation is a narrower question. A correlation is 1 for any straight-line relation between two CLR columns; rho is 1 only when the slope is 1, which on the log scale means the two parts are proportional. In a second toy check, one part is the square of another (<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>=</mo><msup><mi>x</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">y = x^2</annotation></semantics></math>) among 9 other parts: their CLR correlation is 0.98 and their rho is 0.72. Two taxa that rise together, one much more steeply than the other, get a high correlation and a lower rho.</p>
</section>
<section id="changing-the-set-of-parts" class="level2">
<h2 class="anchored" data-anchor-id="changing-the-set-of-parts">Changing the set of parts</h2>
<p>A correlation of proportions also depends on which other parts were measured. The next check scores the same pairs of the rarest half of the taxa twice: once in the full community, and once after the abundant taxa are dropped and the rest re-closed to 100%, as happens when a study reports only one phylum or excludes a contaminant.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the 15 least abundant taxa</span></span>
<span id="cb12-2">n_sets_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="cb12-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260926</span>)</span>
<span id="cb12-4">sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_sets_sub), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) {</span>
<span id="cb12-5">  s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_community</span>(shares_main)</span>
<span id="cb12-6">  full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pc_main</span>
<span id="cb12-7">  pf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> full <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(full)                              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># full community</span></span>
<span id="cb12-8">  pp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> full[, keep] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(full[, keep])              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># subcomposition, re-closed</span></span>
<span id="cb12-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">set =</span> k,</span>
<span id="cb12-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cor_full =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(pf)[keep, keep]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cor_sub =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(pp)),</span>
<span id="cb12-11">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr_full =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(pf))[keep, keep]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clr_sub =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(pp))),</span>
<span id="cb12-12">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho_full =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(pf))[keep, keep]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rho_sub =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rho</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clr</span>(pp))),</span>
<span id="cb12-13">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lrv_diff =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lr_var</span>(pf)[keep, keep]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairs_of</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lr_var</span>(pp)))))</span>
<span id="cb12-14">}))</span>
<span id="cb12-15">cor_shift <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cor_full <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cor_sub))</span>
<span id="cb12-16">clr_shift <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_full <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_sub))</span>
<span id="cb12-17">rho_shift <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho_full <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho_sub))</span>
<span id="cb12-18">lrv_shift <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lrv_diff)</span>
<span id="cb12-19">mean_cor_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cor_full); mean_cor_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cor_sub)</span>
<span id="cb12-20">mean_clr_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_full); mean_clr_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_sub)</span>
<span id="cb12-21">mean_rho_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho_full); mean_rho_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho_sub)</span>
<span id="cb12-22">theory_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(keep) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">sub_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb13-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">full =</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cor_full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">part =</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cor_sub, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">score =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pearson on proportions"</span>),</span>
<span id="cb13-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">full =</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">part =</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>clr_sub, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">score =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pearson on CLR values"</span>),</span>
<span id="cb13-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">full =</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho_full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">part =</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rho_sub, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">score =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rho on CLR values"</span>))</span>
<span id="cb13-5">sub_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>score <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(sub_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>score, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(sub_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>score))</span>
<span id="cb13-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(sub_long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(full, part)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">slope =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">intercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> violet) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> score) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_equal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"score in the full community"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"score in the subcomposition"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-11">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-subcomposition" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three scatter panels. For Pearson correlation of proportions the cloud lies mostly below the diagonal and is spread widely around it. For Pearson correlation of CLR values and for rho the clouds look alike: close to the diagonal and shifted slightly below it.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-subcomposition-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/correlation-of-proportions/index_files/figure-html/fig-subcomposition-1.png" class="img-fluid figure-img" alt="Three scatter panels. For Pearson correlation of proportions the cloud lies mostly below the diagonal and is spread widely around it. For Pearson correlation of CLR values and for rho the clouds look alike: close to the diagonal and shifted slightly below it." width="864">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-subcomposition-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;4: The same pairs of rare taxa scored in the full community (x axis) and after the abundant taxa are removed and the rest re-closed to 100% (y axis), with three scores. Points on the diagonal would mean the score does not depend on which other taxa were measured.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The correlation of proportions depends heavily on what else was measured. For the same pairs of taxa it averages 0.09 in the full community and -0.06 in the subcomposition, and the typical pair moves by 0.15 (median absolute change). Moving to log-ratios removes most of that. The CLR correlation moves by 0.04 and rho by 0.04; their averages go from -0.034 to -0.071 and from -0.033 to -0.070, the <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>−</mi><mn>1</mn><mi>/</mi><mo stretchy="false" form="prefix">(</mo><mi>D</mi><mo>−</mo><mn>1</mn><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">-1/(D - 1)</annotation></semantics></math> of 15 parts being -0.071. The two move the same small amount because both are scaled by CLR variances, and a CLR value depends on the geometric mean of whatever parts are present. The log-ratio variance itself does not move at all: the largest difference is 3e-15, which is floating-point rounding. If a result has to survive a change in which taxa were measured, the log-ratio variance of the pair is the quantity to report.</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>Do not run <code>cor()</code> on proportions, percentages or their logs, and do not build co-occurrence networks from them. One dominant part against everything and the rest mildly positive looks like biology and is arithmetic.</p>
<p>With many parts, compute on CLR values. A pseudocount is needed only because of the zeros; say which one you used, and check that your conclusions hold with a second one. With CLR correlations or rho, report which parts went into the reference, because the numbers depend on it. For finding parts that move together, rho answers a question that relative data can actually support. It has no built-in test, and the propr paper picks its highly proportional pairs with an arbitrary cutoff. A cutoff can instead be calibrated by shuffling each taxon’s counts across samples, which destroys every pairing, and recording how high rho gets by chance:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># samples in rows, taxa in columns</span></span>
<span id="cb14-2">z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(x) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(x))               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># centred log-ratio</span></span>
<span id="cb14-3">v <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(z, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var)</span>
<span id="cb14-4">rho <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cov</span>(z) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(v, v, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"+"</span>)         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># proportionality</span></span>
<span id="cb14-5">lr_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(v, v, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"+"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cov</span>(z)      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># var(log(x_i / x_j)) for every pair</span></span>
<span id="cb14-6"></span>
<span id="cb14-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># permutation null for rho: shuffle each taxon independently, recompute</span></span>
<span id="cb14-8">null_rho <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, {</span>
<span id="cb14-9">  xp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(x, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, sample)</span>
<span id="cb14-10">  zp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(xp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(xp)); vp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(zp, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var)</span>
<span id="cb14-11">  r <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cov</span>(zp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(vp, vp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"+"</span>); r[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">upper.tri</span>(r)]</span>
<span id="cb14-12">})</span>
<span id="cb14-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(null_rho, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.99</span>)                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># rho this high arises by chance in 1% of pairs</span></span></code></pre></div></div>
</div>
<p>With few parts, such as a handful of cell types, accept that the proportions are dependent and ask a question in ratio form instead: does the ratio of B cells to T cells change with treatment? That ratio is a single number per sample and can be tested like any other. If the question is really about absolute numbers (did this cell type expand, or did the others shrink?), it needs a measurement of the total: cells per microlitre from a counter or flow cytometry, a spike-in, or total bacterial load by qPCR. RNA-seq has the same problem when most genes change (<a href="https://pseudocount.com/posts/library-size-vs-composition/">see the post on CPM and TMM</a>), and the same answer: the reference has to come from outside the shares.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Pearson K 1897 Proceedings of the Royal Society of London 60:489-498 (<a href="https://doi.org/10.1098/rspl.1896.0076">doi:10.1098/rspl.1896.0076</a>)</li>
<li>Aitchison J 1982 Journal of the Royal Statistical Society Series B 44(2):139-160 (<a href="https://doi.org/10.1111/j.2517-6161.1982.tb01195.x">doi:10.1111/j.2517-6161.1982.tb01195.x</a>)</li>
<li>Lovell D, Pawlowsky-Glahn V, Egozcue JJ et al.&nbsp;2015 PLOS Computational Biology 11(3):e1004075 (<a href="https://doi.org/10.1371/journal.pcbi.1004075">doi:10.1371/journal.pcbi.1004075</a>)</li>
<li>Gloor GB, Macklaim JM, Pawlowsky-Glahn V et al.&nbsp;2017 Frontiers in Microbiology 8:2224 (<a href="https://doi.org/10.3389/fmicb.2017.02224">doi:10.3389/fmicb.2017.02224</a>)</li>
<li>Quinn TP, Richardson MF, Lovell D et al.&nbsp;2017 Scientific Reports 7:16252 (<a href="https://doi.org/10.1038/s41598-017-16520-0">doi:10.1038/s41598-017-16520-0</a>)</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
ggplot2 4.0.3</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>compositional data</category>
  <category>microbiome</category>
  <category>correlation</category>
  <category>simulation</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/correlation-of-proportions/</guid>
  <pubDate>Mon, 21 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/correlation-of-proportions/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Double dipping: marker gene p-values after clustering</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/double-dipping-single-cell-markers/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(SingleCellExperiment)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(scuttle)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(scran)</span>
<span id="cb1-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(bluster)</span>
<span id="cb1-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-8">})</span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SingleCellExperiment"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.24.0"</span>,</span>
<span id="cb1-10">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scuttle"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.12.0"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scran"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.30.0"</span>,</span>
<span id="cb1-11">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bluster"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.12.0"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>,</span>
<span id="cb1-12">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4.0"</span>)</span>
<span id="cb1-13">fmt_pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f%%"</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-14">fmt_int <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trim =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-15">fmt_num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>), x)</span>
<span id="cb1-16">fmt_p   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.0e"</span>, p)</span>
<span id="cb1-17">fmt_rng <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(v) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(v) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(v)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_int</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(v)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span></span>
<span id="cb1-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_int</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(v)), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"to"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_int</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(v)))</span>
<span id="cb1-19">fmt_prng <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(v, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(v), d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(v), d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb1-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_pct</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(v), d) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_pct</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(v), d), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"to"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_pct</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(v), d))</span>
<span id="cb1-21">fmt_of  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(a, k, noun, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">all =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"All"</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (a <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(all, k, noun) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span></span>
<span id="cb1-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(a, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"of the"</span>, k, noun)</span>
<span id="cb1-23">fmt_n   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(n, noun) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no "</span>, noun, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span></span>
<span id="cb1-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_int</span>(n), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) noun <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(noun, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span>))</span>
<span id="cb1-25">alpha <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>                                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># p-value and FDR threshold</span></span>
<span id="cb1-26">violet <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>; grey <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8799"</span></span>
<span id="cb1-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_set</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-28">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb1-29">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>),</span>
<span id="cb1-30">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">strip.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>)))</span></code></pre></div></div>
</details>
</div>
<p>You cluster your cells, ask for the marker genes of each cluster, and every cluster comes back with genes whose p-values are so small they print in scientific notation. It is tempting to read them as proof that the clusters are real. So the question people type into a search box is: why are my marker p-values so small, and can I trust them?</p>
<p>You cannot, because the same data were used twice: once to draw the cluster boundaries and once to test whether the clusters differ. In 2,000 simulated cells from a single population, with no clusters at all, graph-based clustering found 10 clusters, and a Wilcoxon test of each cluster against the rest called on average 21.5 genes per cluster significant at a false discovery rate (FDR) of 5%. Every one of them is a false positive. Splitting each count into two independent halves, clustering on one and testing on the other, removes the reuse, provided the test on the held-out half also accounts for each cell’s sequencing depth, which both halves share.</p>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">simulate_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_cells =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_genes =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sf_sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>,</span>
<span id="cb2-2">                           <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_sub =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_marker =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fold =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) {</span>
<span id="cb2-3">  mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># mean UMI per cell, per gene</span></span>
<span id="cb2-4">  sf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_cells, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, sf_sd))               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># capture efficiency, per cell</span></span>
<span id="cb2-5">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(mu, sf)</span>
<span id="cb2-6">  sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_cells) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_sub                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># optional real subpopulation</span></span>
<span id="cb2-7">  m[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_marker), sub] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fold <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> m[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_marker), sub]</span>
<span id="cb2-8">  x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (phi <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rpois</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(m), m) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(m), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi)</span>
<span id="cb2-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(x, n_genes, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"g%04d"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes)),</span>
<span id="cb2-10">                                     <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c%04d"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_cells))))</span>
<span id="cb2-11">}</span>
<span id="cb2-12"></span>
<span id="cb2-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-14">counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_cells</span>()</span>
<span id="cb2-15">n_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(counts); n_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(counts)</span>
<span id="cb2-16">sf_sd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(simulate_cells)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sf_sd</span>
<span id="cb2-17">share_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</div>
<p>The simulated data set has 2,000 cells and 1,000 genes. Each gene has a baseline level (48% of genes average less than one UMI per cell; a UMI, or unique molecular identifier, is one captured mRNA molecule). Each cell has a capture efficiency that scales all its counts up or down, with a standard deviation of 0.3 on the natural log scale; this is what makes cells differ in sequencing depth. Counts are Poisson around the product of the two. Every cell comes from the same distribution, so any gene called a marker is a false positive. The Poisson noise is the assumption that matters most, and a later section replaces it with negative binomial noise.</p>
</section>
<section id="the-common-way-cluster-then-test-the-clusters" class="level2">
<h2 class="anchored" data-anchor-id="the-common-way-cluster-then-test-the-clusters">The common way: cluster, then test the clusters</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">as_sce <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">logNormCounts</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SingleCellExperiment</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">counts =</span> counts)))</span>
<span id="cb3-2"></span>
<span id="cb3-3">cluster_pipeline <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_hvg =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_pc =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>) {</span>
<span id="cb3-4">  sce <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_sce</span>(counts)</span>
<span id="cb3-5">  hvg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getTopHVGs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">modelGeneVar</span>(sce), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> n_hvg)</span>
<span id="cb3-6">  sce <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fixedPCA</span>(sce, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rank =</span> n_pc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subset.row =</span> hvg)</span>
<span id="cb3-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(sce)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hvg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> hvg</span>
<span id="cb3-8">  sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clusterCells</span>(sce, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">use.dimred =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA"</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># SNN graph + walktrap</span></span>
<span id="cb3-9">  sce</span>
<span id="cb3-10">}</span>
<span id="cb3-11"></span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># each cluster against all other cells: a Wilcoxon rank-sum p-value per gene</span></span>
<span id="cb3-13">markers_vs_rest <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(sce, cluster) {</span>
<span id="cb3-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(cluster), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) {</span>
<span id="cb3-15">    in_k <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(cluster <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"in"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"out"</span>))</span>
<span id="cb3-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">findMarkers</span>(sce, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">groups =</span> in_k, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test.type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wilcox"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(sce), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p.value"</span>]</span>
<span id="cb3-17">  })</span>
<span id="cb3-18">}</span>
<span id="cb3-19"></span>
<span id="cb3-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># per cluster: how many genes pass a Benjamini-Hochberg FDR of alpha</span></span>
<span id="cb3-21">n_markers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(P) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(P, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, p.adjust, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">sce <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(counts)</span>
<span id="cb4-2">p_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">markers_vs_rest</span>(sce, sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">p_nn <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">NNGraphParam</span>()                               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what clusterCells() uses by default</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">class =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">class</span>(p_nn)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> p_nn<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span>k, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> p_nn<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span>type, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cluster.fun =</span> p_nn<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span>cluster.fun)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>          class               k            type     cluster.fun 
"SNNGraphParam"            "10"          "rank"      "walktrap" </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the default test: findMarkers() without test.type gives the same p-values as test.type = "t"</span></span>
<span id="cb7-2">g2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"in"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"out"</span>))</span>
<span id="cb7-3">same_as_t <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">identical</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">findMarkers</span>(sce[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, ], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">groups =</span> g2)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value,</span>
<span id="cb7-4">                       <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">findMarkers</span>(sce[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, ], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">groups =</span> g2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test.type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"t"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">in</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value)</span>
<span id="cb7-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">default_is_t =</span> same_as_t)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>default_is_t 
        TRUE </code></pre>
</div>
</div>
<p>The pipeline is the standard Bioconductor one: log-normalise with <code>logNormCounts()</code>, keep the most variable genes, reduce them to 10 principal components, and cluster with <code>clusterCells()</code>, whose default builds a shared nearest-neighbour graph from the 10 nearest neighbours of each cell and splits it with the walktrap algorithm (output above); Seurat and scanpy do the same with Louvain or Leiden. For markers, <code>findMarkers()</code> compares each cluster with all other cells using <code>test.type = "wilcox"</code>, a two-sided Wilcoxon rank-sum test (its default is a t-test, as the check shows; Seurat’s <code>FindMarkers()</code> defaults to the Wilcoxon test), with Benjamini-Hochberg adjustment within each cluster.</p>
<p>The clustering found 10 clusters in data that has none. Figure&nbsp;1 shows them on the first two principal components: one continuous cloud of cells, cut into pieces.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">pcs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reducedDim</span>(sce, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA"</span>)</span>
<span id="cb9-2">dpc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">PC1 =</span> pcs[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">PC2 =</span> pcs[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cluster =</span> sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span>
<span id="cb9-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dpc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(PC1, PC2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> cluster)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hcl.colors</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nlevels</span>(dpc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dark 3"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">guides</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">guide_legend</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">override.aes =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cluster"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-pca" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Scatter plot of principal component 1 against principal component 2 for all simulated cells. The points form one continuous cloud with no gaps, and the cluster colours occupy overlapping regions of it, with some clusters towards the left edge and others towards the right.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-pca-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/double-dipping-single-cell-markers/index_files/figure-html/fig-pca-1.png" class="img-fluid figure-img" alt="Scatter plot of principal component 1 against principal component 2 for all simulated cells. The points form one continuous cloud with no gaps, and the cluster colours occupy overlapping regions of it, with some clusters towards the left edge and others towards the right." width="624">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-pca-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: The simulated cells on the first two principal components, coloured by the clusters that graph-based clustering found. The cells come from a single population; the clusters are pieces of one cloud.
</figcaption>
</figure>
</div>
</div>
</div>
<p>All 10 clusters got marker genes at an FDR of 5%, between 6 and 49 per cluster, with a smallest p-value of 1e-19. Across every gene and every cluster, 12% of the raw p-values fell below 0.05, where a valid test on null data gives 5%.</p>
</section>
<section id="why-it-happens" class="level2">
<h2 class="anchored" data-anchor-id="why-it-happens">Why it happens</h2>
<p>A clustering algorithm has one job: find groups of cells that differ in expression. In data without structure, noise still makes some cells a little higher in some genes and a little lower in others, and the algorithm puts its boundaries where those chance differences line up best. The marker test then asks whether the groups differ. They do, because that is how the groups were chosen.</p>
<p>The p-value of a Wilcoxon test (or a t-test) assumes the groups were fixed before anyone looked at the data. Here they were chosen from the same counts that are then tested: the data are used once to pick the hypothesis and again to test it. Zhang, Kamath and Tse (2019) describe this for single-cell clustering: because clustering forces the groups apart, reusing the data gives artificially low p-values. They also propose a corrected test.</p>
<p>The inflation sits where the clustering looked. Among the 352 variable genes that went into the principal components (<code>getTopHVGs()</code> was asked for up to 500 but by default keeps only genes above the fitted mean-variance trend), 21% of the p-values fell below 0.05; among the other genes, 7%.</p>
<p>The clustering also picked up something real, if uninteresting: sequencing depth. The first principal component correlates with the log of each cell’s total count (correlation 0.68), and the clusters account for 33% of the variance in log total count. Log-normalisation does not remove depth completely (a cell with fewer counts has more zeros), so clusters that differ in depth also differ a little in the normalised values of every gene, which is the likely reason the genes the clustering never used came out at 7% rather than 5%. This matters again below.</p>
</section>
<section id="the-tempting-fix-split-the-cells" class="level2">
<h2 class="anchored" data-anchor-id="the-tempting-fix-split-the-cells">The tempting fix: split the cells</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># assign held-out cells to the nearest cluster centre in the training PCA space</span></span>
<span id="cb10-2">assign_heldout <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(train_sce, test_sce) {</span>
<span id="cb10-3">  hvg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(train_sce)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hvg</span>
<span id="cb10-4">  rot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">attr</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reducedDim</span>(train_sce, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA"</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rotation"</span>)[hvg, ]</span>
<span id="cb10-5">  centre <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">logcounts</span>(train_sce)[hvg, ]))</span>
<span id="cb10-6">  z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">logcounts</span>(test_sce)[hvg, ]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> centre) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> rot</span>
<span id="cb10-7">  cent <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowsum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reducedDim</span>(train_sce, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA"</span>), train_sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span></span>
<span id="cb10-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(train_sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster))</span>
<span id="cb10-9">  d2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(z<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(cent<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"+"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> z <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%*%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(cent)</span>
<span id="cb10-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(cent)[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max.col</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>d2)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(cent))</span>
<span id="cb10-11">}</span>
<span id="cb10-12"></span>
<span id="cb10-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb10-14">half <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(n_cells, n_cells <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb10-15">sce_a <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(counts[, half])            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cluster on half A</span></span>
<span id="cb10-16">sce_b <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_sce</span>(counts[, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>half])                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># test on half B</span></span>
<span id="cb10-17">cl_b <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">droplevels</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">assign_heldout</span>(sce_a, sce_b))</span>
<span id="cb10-18">p_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">markers_vs_rest</span>(sce_b, cl_b)</span></code></pre></div></div>
</div>
<p>The textbook answer is to use different data for the two steps: cluster half of the cells, test in the other half. But the held-out cells have no cluster labels, and the only way to give them one is from their own expression (above: project each onto the training principal components and pick the nearest cluster centre, the idea behind label transfer).</p>
<p>That puts the circularity back. Half A gave 7 clusters; in half B, 7 of them got markers, 6.7 per cluster on average, with a smallest p-value of 2e-09, and 9% of the raw p-values were below 0.05. Half as many cells means less power, but the share of small p-values stays well above 5%, because each held-out cell was sorted into a cluster by the genes that are then tested. Neufeld et al.&nbsp;(2024) make the same point: sample splitting, the usual remedy elsewhere, does not apply here.</p>
</section>
<section id="count-splitting-and-the-depth-both-halves-share" class="level2">
<h2 class="anchored" data-anchor-id="count-splitting-and-the-depth-both-halves-share">Count splitting, and the depth both halves share</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">count_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) {</span>
<span id="cb11-2">  p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> eps                                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Poisson: binomial thinning</span></span>
<span id="cb11-3">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.null</span>(phi)) {                               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># negative binomial: beta-binomial</span></span>
<span id="cb11-4">    b <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pmax</span>(phi, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-8</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(counts))</span>
<span id="cb11-5">    p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbeta</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(counts), eps <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> b, (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> eps) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> b)</span>
<span id="cb11-6">  }</span>
<span id="cb11-7">  train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(counts), counts, p), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(counts),</span>
<span id="cb11-8">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dimnames</span>(counts))</span>
<span id="cb11-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">train =</span> train, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test =</span> counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> train)</span>
<span id="cb11-10">}</span>
<span id="cb11-11"></span>
<span id="cb11-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># negative binomial GLM in edgeR; the offset is each cell's log total count (no TMM)</span></span>
<span id="cb11-13">nb_vs_rest <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, cluster, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clusters =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(cluster)) {</span>
<span id="cb11-14">  design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cluster)</span>
<span id="cb11-15">  fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(counts), design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb11-16">  K <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nlevels</span>(cluster)</span>
<span id="cb11-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(clusters, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) {                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cluster k against the mean of the others</span></span>
<span id="cb11-18">    con <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(cluster) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (K <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb11-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> con)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue</span>
<span id="cb11-20">  })</span>
<span id="cb11-21">}</span>
<span id="cb11-22"></span>
<span id="cb11-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb11-24">cs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count_split</span>(counts)</span>
<span id="cb11-25">sce_train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(cs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>train)              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cluster on the training counts</span></span>
<span id="cb11-26">sce_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_sce</span>(cs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test)                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># test on the held-out counts</span></span>
<span id="cb11-27">p_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">markers_vs_rest</span>(sce_test, sce_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span>
<span id="cb11-28">p_split_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nb_vs_rest</span>(cs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test, sce_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span></code></pre></div></div>
</div>
<p>Count splitting (Neufeld et al.&nbsp;2024) splits the counts instead of the cells. Every UMI is sent to a training copy or a test copy by a coin flip: for a count <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>x</mi><annotation encoding="application/x-tex">x</annotation></semantics></math>, the training count is binomial with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>x</mi><annotation encoding="application/x-tex">x</annotation></semantics></math> trials and probability 0.5, and the rest goes to the test copy. If the original count is Poisson, the two copies are independent Poisson counts. Both copies contain every cell, so the clusters found on the training copy label the same cells in the test copy, and the test copy had no say in where the boundaries went. The whole pipeline runs on the training counts; only the marker test uses the test counts.</p>
<p>Independence covers the noise, not what the copies share: both copies of a cell inherit its capture efficiency, so clusters that follow depth in the training copy differ in depth in the test copy too, and a Wilcoxon test on log-normalised values can see that. A test that models the counts with each cell’s total count as an offset does not: <code>nb_vs_rest()</code> above fits edgeR’s negative binomial quasi-likelihood model (with <code>legacy = FALSE</code>, <code>glmQLFit()</code> estimates the negative binomial dispersion itself, so no <code>estimateDisp()</code> step is needed) and compares each cluster with the average of the others.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">clusterings <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"walktrap, k = 10"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">NNGraphParam</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>),</span>
<span id="cb12-2">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Louvain, k = 20"</span>  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">NNGraphParam</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cluster.fun =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"louvain"</span>))</span>
<span id="cb12-3">wide_sd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>                                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a wider spread of sequencing depth</span></span>
<span id="cb12-4">r2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(y, cl) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lm</span>(y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> cl))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>r.squared</span>
<span id="cb12-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span>
<span id="cb12-6">runs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(); per_cluster <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>()</span>
<span id="cb12-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (job <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(sf_sd, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(sf_sd, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(wide_sd, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))) {</span>
<span id="cb12-8">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> job[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]; s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> job[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb12-9">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sf_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> s <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) { cs_s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cs; tr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sce_train } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb12-10">    cs_s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count_split</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_cells</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sf_sd =</span> d))</span>
<span id="cb12-11">    tr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(cs_s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>train)</span>
<span id="cb12-12">  }</span>
<span id="cb12-13">  te <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_sce</span>(cs_s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test)</span>
<span id="cb12-14">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (j <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(clusterings)) {</span>
<span id="cb12-15">    cl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) tr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span></span>
<span id="cb12-16">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clusterCells</span>(tr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">use.dimred =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">BLUSPARAM =</span> clusterings[[j]])</span>
<span id="cb12-17">    main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sf_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> s <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb12-18">    p_w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (main) p_split <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">markers_vs_rest</span>(te, cl)</span>
<span id="cb12-19">    run_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> s <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR is slow: first clustering only</span></span>
<span id="cb12-20">    p_e <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (main) p_split_nb <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (run_nb) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nb_vs_rest</span>(cs_s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test, cl) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb12-21">    runs[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(runs) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb12-22">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">depth_sd =</span> d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data_set =</span> s, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clustering =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(clusterings)[j], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clusters =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nlevels</span>(cl),</span>
<span id="cb12-23">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">depth_R2 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">r2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(cs_s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test)), cl), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb12-24">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">wilcox_markers =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_w)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">wilcox_p_below =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_w <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb12-25">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edgeR_markers =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (run_nb) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_e)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb12-26">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edgeR_p_below =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (run_nb) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_e <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-27">    per_cluster[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(per_cluster) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb12-28">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">depth_sd =</span> d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wilcoxon"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_w)),</span>
<span id="cb12-29">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (run_nb) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">depth_sd =</span> d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_e)))</span>
<span id="cb12-30">  }</span>
<span id="cb12-31">}</span>
<span id="cb12-32">runs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, runs); per_cluster <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, per_cluster)</span>
<span id="cb12-33">lo <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> runs[runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>depth_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sf_sd, ]; hi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> runs[runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>depth_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> wide_sd, ]</span>
<span id="cb12-34">nb_runs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> runs[runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_markers <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, ]</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">shown <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> runs</span>
<span id="cb13-2">shown<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_markers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_markers <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"not run"</span>, runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_markers)</span>
<span id="cb13-3">shown<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_p_below <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_p_below <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"not run"</span>, runs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>edgeR_p_below)</span>
<span id="cb13-4">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(shown)</span></code></pre></div></div>
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 8%">
<col style="width: 8%">
<col style="width: 15%">
<col style="width: 8%">
<col style="width: 8%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 12%">
<col style="width: 12%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: right;">depth_sd</th>
<th style="text-align: right;">data_set</th>
<th style="text-align: left;">clustering</th>
<th style="text-align: right;">clusters</th>
<th style="text-align: right;">depth_R2</th>
<th style="text-align: right;">wilcox_markers</th>
<th style="text-align: right;">wilcox_p_below</th>
<th style="text-align: left;">edgeR_markers</th>
<th style="text-align: left;">edgeR_p_below</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: right;">0.3</td>
<td style="text-align: right;">1</td>
<td style="text-align: left;">walktrap, k = 10</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;">0.21</td>
<td style="text-align: right;">11</td>
<td style="text-align: right;">0.086</td>
<td style="text-align: left;">0</td>
<td style="text-align: left;">0.051</td>
</tr>
<tr class="even">
<td style="text-align: right;">0.3</td>
<td style="text-align: right;">1</td>
<td style="text-align: left;">Louvain, k = 20</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;">0.21</td>
<td style="text-align: right;">15</td>
<td style="text-align: right;">0.082</td>
<td style="text-align: left;">not run</td>
<td style="text-align: left;">not run</td>
</tr>
<tr class="odd">
<td style="text-align: right;">0.3</td>
<td style="text-align: right;">2</td>
<td style="text-align: left;">walktrap, k = 10</td>
<td style="text-align: right;">6</td>
<td style="text-align: right;">0.22</td>
<td style="text-align: right;">13</td>
<td style="text-align: right;">0.097</td>
<td style="text-align: left;">not run</td>
<td style="text-align: left;">not run</td>
</tr>
<tr class="even">
<td style="text-align: right;">0.3</td>
<td style="text-align: right;">2</td>
<td style="text-align: left;">Louvain, k = 20</td>
<td style="text-align: right;">6</td>
<td style="text-align: right;">0.20</td>
<td style="text-align: right;">39</td>
<td style="text-align: right;">0.092</td>
<td style="text-align: left;">not run</td>
<td style="text-align: left;">not run</td>
</tr>
<tr class="odd">
<td style="text-align: right;">0.5</td>
<td style="text-align: right;">1</td>
<td style="text-align: left;">walktrap, k = 10</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;">0.53</td>
<td style="text-align: right;">1688</td>
<td style="text-align: right;">0.620</td>
<td style="text-align: left;">0</td>
<td style="text-align: left;">0.05</td>
</tr>
<tr class="even">
<td style="text-align: right;">0.5</td>
<td style="text-align: right;">1</td>
<td style="text-align: left;">Louvain, k = 20</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;">0.51</td>
<td style="text-align: right;">1703</td>
<td style="text-align: right;">0.594</td>
<td style="text-align: left;">not run</td>
<td style="text-align: left;">not run</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The table repeats the count split on 2 data sets with the depth spread used so far (0.3) and one with a wider spread (0.5), each training copy clustered in 2 ways; <code>depth_R2</code> is the share of variance in the test copy’s log total count that the clusters account for. At the narrower spread the clusters accounted for 20% to 22% of it, and the Wilcoxon test gave 11 to 39 marker genes per clustering, with 8.2% to 9.7% of p-values below 0.05. Small counts like these move around with the clustering, the seed and the package versions. At the wider spread they accounted for 51% to 53%, and the Wilcoxon test gave 1,688 to 1,703 marker genes per clustering, with 59% to 62% of p-values below 0.05. The copies share nothing else, so those markers come from depth, not from double dipping. The edgeR model, run on the first clustering of the first data set at each spread, gave 0 marker genes per clustering in the runs shown, with 5.0% to 5.1% of p-values below 0.05. Over other clusterings it will sometimes report a few markers, about as many as Benjamini-Hochberg lets through by chance when nothing is there (a false marker in up to about 5% of clusters), at either depth spread.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">lab_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"same cells,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">same counts"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split cells"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split counts,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Wilcoxon"</span>,</span>
<span id="cb14-2">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split counts,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">edgeR"</span>)</span>
<span id="cb14-3">dp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_p[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(p_naive)),</span>
<span id="cb14-4">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_p[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(p_cells)),</span>
<span id="cb14-5">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_p[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(p_split)),</span>
<span id="cb14-6">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_p[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(p_split_nb)))</span>
<span id="cb14-7">dp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>approach <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(dp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>approach, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> lab_p)</span>
<span id="cb14-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dp, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(p)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">after_stat</span>(density)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>),</span>
<span id="cb14-10">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> violet, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> approach, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value (every gene, every cluster against the rest)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"density"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-pvalues" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Four p-value histograms side by side. In the same-cells-same-counts panel and the split-cells panel, the bar at the left edge stands clearly above the others. The two split-counts panels, Wilcoxon and edgeR, sit close to the dashed uniform line.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-pvalues-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/double-dipping-single-cell-markers/index_files/figure-html/fig-pvalues-1.png" class="img-fluid figure-img" alt="Four p-value histograms side by side. In the same-cells-same-counts panel and the split-cells panel, the bar at the left edge stands clearly above the others. The two split-counts panels, Wilcoxon and edgeR, sit close to the dashed uniform line." width="816">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-pvalues-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: P-values from testing each cluster against the rest, for every gene, in the data with no real clusters (narrower depth spread, default clustering). A valid test gives a flat histogram (dashed line). Testing on the cells and counts used for clustering, or on held-out cells, piles p-values up near zero.
</figcaption>
</figure>
</div>
</div>
</div>
<p>Count splitting does not stop the algorithm from finding clusters in noise (the training copy was still cut into 8 pieces); it makes the tested noise different from the noise that drew the boundaries. In real data, batch, cell cycle and anything else that differs between cells sits in both copies, like depth here, and belongs in the test’s model too.</p>
</section>
<section id="the-assumption-that-matters-poisson-noise" class="level2">
<h2 class="anchored" data-anchor-id="the-assumption-that-matters-poisson-noise">The assumption that matters: Poisson noise</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># method-of-moments negative binomial overdispersion, one value per gene</span></span>
<span id="cb15-2">nb_dispersion <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts) {</span>
<span id="cb15-3">  sf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(counts))</span>
<span id="cb15-4">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(sf), sf)</span>
<span id="cb15-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pmax</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>((counts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> m)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> m) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb15-6">}</span>
<span id="cb15-7"></span>
<span id="cb15-8">phi_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span></span>
<span id="cb15-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb15-10">counts_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_cells</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> phi_nb)</span>
<span id="cb15-11">phi_hat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nb_dispersion</span>(counts_nb)</span>
<span id="cb15-12"></span>
<span id="cb15-13">cs_pois <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count_split</span>(counts_nb)                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># assumes Poisson</span></span>
<span id="cb15-14">tr_pois <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(cs_pois<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>train)</span>
<span id="cb15-15">p_nb_pois <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">markers_vs_rest</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_sce</span>(cs_pois<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test), tr_pois<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span>
<span id="cb15-16"></span>
<span id="cb15-17">cs_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count_split</span>(counts_nb, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> phi_hat)        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># uses the estimated overdispersion</span></span>
<span id="cb15-18">tr_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(cs_nb<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>train)</span>
<span id="cb15-19">p_nb_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">markers_vs_rest</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_sce</span>(cs_nb<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test), tr_nb<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span></code></pre></div></div>
</div>
<p>Independence of the two copies holds for Poisson counts. Real UMI counts are often more variable (overdispersed, usually modelled as negative binomial). Then a cell with a burst of one gene has a high count in both copies, the copies are positively correlated, and double dipping comes back through those genes. The next simulation gives every gene negative binomial noise with overdispersion 0.5 (variance = mean + 0.5 x mean squared) and still no clusters. After a Poisson split, 7 of the 8 training clusters got markers in the test copy, 22 in total, with a smallest p-value of 1e-31 (against 1e-19 for the same-data analysis on Poisson data). Only 6.4% of all raw p-values were below 0.05, so the damage sits in a few genes with extreme p-values that a histogram can hide.</p>
<p>The fix is a split that matches the noise. Draw the thinning probability for each count from a beta distribution set by the overdispersion, then split binomially with it. Seen as a Poisson count whose mean varies from cell to cell, this divides the varying mean itself into two independent parts, and the copies are independent negative binomial counts again (the <code>phi</code> branch of <code>count_split()</code>). With per-gene overdispersion estimated by the method of moments (median 0.49, true value 0.5), the test copy gave no marker genes across 9 clusters. Both analyses here use the Wilcoxon test to keep the run short; the narrower-spread rows of the table show what depth alone adds at this spread. The estimate must be right in both directions: too small leaves the copies positively correlated, too large makes them negatively correlated.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">lab_m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"same cells, same counts"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split cells"</span>,</span>
<span id="cb16-2">           <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split counts, Wilcoxon, depth sd"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_num</span>(sf_sd)),</span>
<span id="cb16-3">           <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split counts, Wilcoxon, depth sd"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt_num</span>(wide_sd)),</span>
<span id="cb16-4">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split counts, edgeR, both spreads"</span>,</span>
<span id="cb16-5">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"overdispersed: Poisson split"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"overdispersed: NB split"</span>)</span>
<span id="cb16-6">pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(test, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(sf_sd, wide_sd))</span>
<span id="cb16-7">  per_cluster<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n[per_cluster<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> test <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> per_cluster<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>depth_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> d]</span>
<span id="cb16-8">dm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_naive)),</span>
<span id="cb16-9">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_cells)),</span>
<span id="cb16-10">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pc</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wilcoxon"</span>, sf_sd)),</span>
<span id="cb16-11">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pc</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wilcoxon"</span>, wide_sd)),</span>
<span id="cb16-12">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pc</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>)),</span>
<span id="cb16-13">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_nb_pois)),</span>
<span id="cb16-14">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">approach =</span> lab_m[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_nb_nb)))</span>
<span id="cb16-15">dm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>approach <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(dm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>approach, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(lab_m))</span>
<span id="cb16-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dm, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(n, approach)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">position_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb16-18">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> violet) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trans =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log1p"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marker genes per cluster at FDR &lt;"</span>, alpha, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(log scale)"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-markers" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Dot strip chart with seven rows on a log scale, one dot per cluster. Same cells and same counts: dots well above zero. Split cells: dots spread from near zero upwards. Split counts with the Wilcoxon test at the narrower depth spread: dots at or near zero. The same at the wider depth spread: some dots in the hundreds, others near zero. Split counts with edgeR: dots at or near zero. Poisson split on overdispersed data: dots above zero. Negative binomial split on overdispersed data: dots at or near zero.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-markers-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/double-dipping-single-cell-markers/index_files/figure-html/fig-markers-1.png" class="img-fluid figure-img" alt="Dot strip chart with seven rows on a log scale, one dot per cluster. Same cells and same counts: dots well above zero. Split cells: dots spread from near zero upwards. Split counts with the Wilcoxon test at the narrower depth spread: dots at or near zero. The same at the wider depth spread: some dots in the hundreds, others near zero. Split counts with edgeR: dots at or near zero. Poisson split on overdispersed data: dots above zero. Negative binomial split on overdispersed data: dots at or near zero." width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-markers-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Marker genes per cluster in data with no real clusters; each point is one cluster, on a log scale. The split-counts rows pool the clusters of the repeated runs in the table; the other rows are single runs.
</figcaption>
</figure>
</div>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">k_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(p_naive); fpr_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_naive <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha)</span>
<span id="cb17-2">mk_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_naive)); any_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_naive) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb17-3">minp_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(p_naive); mk_naive_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_naive))</span>
<span id="cb17-4">k_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(p_cells); fpr_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_cells <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha); minp_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(p_cells)</span>
<span id="cb17-5">mk_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_cells)); any_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_cells) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb17-6">k_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(p_split)</span>
<span id="cb17-7">k_nbp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(p_nb_pois); any_nbp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_nb_pois) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb17-8">tot_nbp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_nb_pois)); minp_nbp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(p_nb_pois)</span>
<span id="cb17-9">fpr_nbp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_nb_pois <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha)</span>
<span id="cb17-10">k_nbnb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(p_nb_nb); tot_nbnb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_markers</span>(p_nb_nb))</span>
<span id="cb17-11">phi_hat_med <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(phi_hat); phi_hat_pois_med <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nb_dispersion</span>(counts))</span>
<span id="cb17-12">hvg_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(sce) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(sce)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hvg; n_hvg_used <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(hvg_naive)</span>
<span id="cb17-13">fpr_hvg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_naive[hvg_naive, ] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha); fpr_other <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p_naive[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>hvg_naive, ] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha)</span>
<span id="cb17-14">n_hvg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(cluster_pipeline)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_hvg; n_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(cluster_pipeline)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_pc</span>
<span id="cb17-15">cor_pc1_lib <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reducedDim</span>(sce, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PCA"</span>)[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(counts))))</span>
<span id="cb17-16">r2_lib_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">r2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(counts)), sce<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)</span></code></pre></div></div>
</div>
</section>
<section id="does-count-splitting-still-find-real-clusters" class="level2">
<h2 class="anchored" data-anchor-id="does-count-splitting-still-find-real-clusters">Does count splitting still find real clusters?</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">n_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>; n_true <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>; fold_true <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb18-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb18-3">counts_pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_cells</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_sub =</span> n_sub, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_marker =</span> n_true, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fold =</span> fold_true)</span>
<span id="cb18-4">is_sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_cells) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_sub</span>
<span id="cb18-5">is_true <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_true</span>
<span id="cb18-6">cs_pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count_split</span>(counts_pos)</span>
<span id="cb18-7">tr_pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(cs_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>train)</span>
<span id="cb18-8">cl_pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tr_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster</span>
<span id="cb18-9">best <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(is_sub, cl_pos, mean)))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cluster holding the subpopulation</span></span>
<span id="cb18-10">q_pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nb_vs_rest</span>(cs_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test, cl_pos, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">clusters =</span> best)[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>)</span>
<span id="cb18-11">lower <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(cs_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test[, cl_pos <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> best]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(cs_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test[, cl_pos <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> best]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span></span>
<span id="cb18-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(cs_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test[, cl_pos <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> best]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(cs_pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test[, cl_pos <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> best])</span>
<span id="cb18-13">pos <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cells_found =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(cl_pos[is_sub] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> best), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">purity =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(is_sub[cl_pos <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> best]),</span>
<span id="cb18-14">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_found =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(q_pos[is_true] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false_found =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(q_pos[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_true] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha),</span>
<span id="cb18-15">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false_lower =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(q_pos[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_true] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> lower[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_true]))</span></code></pre></div></div>
</div>
<p>Halving the counts costs information, so does a real cluster survive? The last simulation adds one: 200 of the 2,000 cells express 30 genes at 3 times the baseline level. The training copy put 100.0% of them in one cluster (which was 100% subpopulation cells), and the edgeR test on the test copy found 30 of the 30 markers. A clear subpopulation stays clear with half the counts; a subtle one may not, and that is the price of an honest p-value.</p>
<p>The test also flagged 11 other genes for that cluster, 11 of them lower there than elsewhere. That is the known weakness of a total-count offset (composition bias): the subpopulation’s extra RNA from its 30 marker genes raises its total count, so every other gene’s share of it falls. Many strongly up-regulated genes in one cluster will do this with any total-count normalisation.</p>
</section>
<section id="the-same-check-in-python" class="level2">
<h2 class="anchored" data-anchor-id="the-same-check-in-python">The same check in Python</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1">py <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read.csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"double_dipping_check-results.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb19-2">pyv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>value, py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>name)</span>
<span id="cb19-3">py_num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pyv[[k]])</span>
<span id="cb19-4">py_k_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"naive_n_clusters"</span>); py_mk_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"naive_markers_per_cluster"</span>)</span>
<span id="cb19-5">py_any_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"naive_clusters_with_marker"</span>); py_fpr_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"naive_fpr"</span>)</span>
<span id="cb19-6">py_k_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split_n_clusters"</span>); py_mk_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split_markers_per_cluster"</span>)</span>
<span id="cb19-7">py_any_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split_clusters_with_marker"</span>); py_fpr_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"split_fpr"</span>)</span>
<span id="cb19-8">py_scanpy <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pyv[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scanpy_version"</span>]]</span></code></pre></div></div>
</div>
<p>The script below runs one null simulation through the usual scanpy steps, ending in <code>rank_genes_groups</code> with the Wilcoxon test against the rest and the tie correction switched on (its default is <code>tie_correct = False</code>) to match the R test. The numbers come from scanpy 1.11.5 and a different random generator. Leiden found 16 clusters, 16 of them with markers (16.7 per cluster on average, 12% of raw p-values below 0.05). After a Poisson count split, 3 of 16 clusters had a marker (0.44 per cluster) and 6.2% of raw p-values were below 0.05; with a Wilcoxon test on log-normalised values, the depth effect described above is the likely source of those.</p>
<div class="cell" data-python.reticulate="false">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Double dipping in scanpy: cluster cells from ONE population, then test markers between clusters.</span></span>
<span id="cb20-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Same design as the R code in the post: 2,000 cells, 1,000 genes, Poisson counts, no clusters.</span></span>
<span id="cb20-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Writes double_dipping_check-results.csv (columns name,value).</span></span>
<span id="cb20-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> importlib.metadata <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> version</span>
<span id="cb20-5"></span>
<span id="cb20-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> anndata <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> ad</span>
<span id="cb20-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb20-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb20-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> scanpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sc</span>
<span id="cb20-10"></span>
<span id="cb20-11">rng <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.default_rng(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb20-12">n_cells, n_genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span></span>
<span id="cb20-13"></span>
<span id="cb20-14">mu <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(rng.normal(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, n_genes))          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># gene means, UMI per cell</span></span>
<span id="cb20-15">sf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(rng.normal(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, n_cells))          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># capture efficiency per cell</span></span>
<span id="cb20-16">counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.poisson(sf[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mu[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :])     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cells x genes, one population</span></span>
<span id="cb20-17">genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"g</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:04d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_genes)]</span>
<span id="cb20-18">cells <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"c</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:04d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_cells)]</span>
<span id="cb20-19"></span>
<span id="cb20-20"></span>
<span id="cb20-21"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make(x):</span>
<span id="cb20-22">    a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ad.AnnData(X<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>x.astype(np.float32), obs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pd.DataFrame(index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cells),</span>
<span id="cb20-23">                   var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pd.DataFrame(index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>genes))</span>
<span id="cb20-24">    sc.pp.normalize_total(a)                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default: scale to the median total count</span></span>
<span id="cb20-25">    sc.pp.log1p(a)</span>
<span id="cb20-26">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a</span>
<span id="cb20-27"></span>
<span id="cb20-28"></span>
<span id="cb20-29"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> cluster(a):</span>
<span id="cb20-30">    sc.pp.highly_variable_genes(a, n_top_genes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>)</span>
<span id="cb20-31">    sc.pp.pca(a, n_comps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, mask_var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"highly_variable"</span>)</span>
<span id="cb20-32">    sc.pp.neighbors(a, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb20-33">    sc.tl.leiden(a, flavor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"igraph"</span>, n_iterations<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, directed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb20-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a.obs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"leiden"</span>]</span>
<span id="cb20-35"></span>
<span id="cb20-36"></span>
<span id="cb20-37"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> markers(a, labels):</span>
<span id="cb20-38">    a.obs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cl"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> labels.values</span>
<span id="cb20-39">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># each cluster vs rest; tie_correct=True to match the R test (scanpy's default is False)</span></span>
<span id="cb20-40">    sc.tl.rank_genes_groups(a, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cl"</span>, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wilcoxon"</span>, tie_correct<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb20-41">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sc.get.rank_genes_groups_df(a, group<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span>
<span id="cb20-42">    per <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>, observed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pvals_adj"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> q: np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(q <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>))</span>
<span id="cb20-43">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_clusters"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(labels.nunique()),</span>
<span id="cb20-44">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(np.mean(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pvals"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)),</span>
<span id="cb20-45">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"markers_per_cluster"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(per.mean()),</span>
<span id="cb20-46">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"clusters_with_marker"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(per <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))}</span>
<span id="cb20-47"></span>
<span id="cb20-48"></span>
<span id="cb20-49"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. the common way: cluster and test on the same cells and counts</span></span>
<span id="cb20-50">adata <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make(counts)</span>
<span id="cb20-51">naive <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> markers(adata, cluster(adata))</span>
<span id="cb20-52"></span>
<span id="cb20-53"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. count splitting: Poisson thinning, cluster on train, test on test</span></span>
<span id="cb20-54">train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.binomial(counts, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb20-55">test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> train</span>
<span id="cb20-56">labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cluster(make(train))</span>
<span id="cb20-57">split <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> markers(make(test), labels)</span>
<span id="cb20-58"></span>
<span id="cb20-59">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"naive_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>k<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>: v <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> naive.items()}</span>
<span id="cb20-60">rows.update({<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"split_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>k<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>: v <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> split.items()})</span>
<span id="cb20-61">rows.update({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_cells"</span>: n_cells, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_genes"</span>: n_genes,</span>
<span id="cb20-62">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scanpy_version"</span>: version(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scanpy"</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"anndata_version"</span>: version(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"anndata"</span>),</span>
<span id="cb20-63">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"leidenalg_version"</span>: version(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"leidenalg"</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"igraph_version"</span>: version(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"igraph"</span>)})</span>
<span id="cb20-64">pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(rows), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(rows.values())}).to_csv(</span>
<span id="cb20-65">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"double_dipping_check-results.csv"</span>, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb20-66"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(pd.Series(rows))</span></code></pre></div></div>
</div>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>Use marker p-values after clustering to rank genes within a cluster, not as evidence. A small p-value says the genes differ between groups that were built to differ; it cannot tell you whether the cluster is a cell type or a cut through a continuum. Effect sizes (a log-fold change, or the AUC that <code>findMarkers()</code> reports with its Wilcoxon p-values) do that job without looking like evidence.</p>
<p>When you need a p-value that means something, for example to claim a new subpopulation, split the raw UMI counts (not normalised or integrated values) before anything else, run the whole pipeline on the training copy, and test the test copy with a count model that includes each cell’s total count:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># counts: raw UMI matrix, genes x cells</span></span>
<span id="cb21-2">cs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count_split</span>(counts)                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Poisson split; see below for overdispersed counts</span></span>
<span id="cb21-3">train <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_pipeline</span>(cs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>train)        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># normalise, HVGs, PCA, cluster: training copy only</span></span>
<span id="cb21-4">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nb_vs_rest</span>(cs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test, train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cluster)    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR, total count as offset; slow on many cells</span></span></code></pre></div></div>
</div>
<p>Add batch and other known cell-level factors to that model’s design. Check the noise model before splitting: <code>nb_dispersion()</code> gave a median of 0.00 on the Poisson data and 0.49 on the overdispersed data. It assumes one population, so on real data estimate it within cells you believe to be one population, or from a model that includes the clusters. The authors’ countsplit package on CRAN (<code>install.packages("countsplit")</code>) does both Poisson and negative binomial splitting in one function, <code>countsplit()</code>; see its <a href="https://anna-neufeld.github.io/countsplit/">documentation</a>.</p>
<p>All of this is about comparing clusters within one data set. Comparing the same cell type between conditions is a different question, with its own trap: <a href="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/">cells are not replicates</a> there either.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Zhang JM, Kamath GM, Tse DN 2019 Cell Systems 9(4):383-392.e6 (<a href="https://doi.org/10.1016/j.cels.2019.07.012">doi:10.1016/j.cels.2019.07.012</a>)</li>
<li>Neufeld A, Gao LL, Popp J, et al.&nbsp;2024 Biostatistics 25(1):270-287 (<a href="https://doi.org/10.1093/biostatistics/kxac047">doi:10.1093/biostatistics/kxac047</a>)</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, bluster 1.20.0, edgeR 4.8.2,
generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0,
limma 3.66.0, MatrixGenerics 1.22.0, matrixStats 1.5.0, S4Vectors
0.48.1, scran 1.38.1, scuttle 1.20.0, Seqinfo 1.0.0,
SingleCellExperiment 1.32.0, SummarizedExperiment 1.40.0
Python part: scanpy 1.11.5, anndata 0.12.19, leidenalg 0.12.0, igraph 1.0.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>scRNA-seq</category>
  <category>clustering</category>
  <category>marker genes</category>
  <category>scanpy</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/double-dipping-single-cell-markers/</guid>
  <pubDate>Thu, 17 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/double-dipping-single-cell-markers/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Interaction terms in DESeq2: what they test</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/interaction-terms-deseq2/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-4">})</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.40"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4"</span>)</span>
<span id="cb1-6">pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.*f%%"</span>, d, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-7">num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.*f"</span>, d, x)</span>
<span id="cb1-8">int <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trim =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-9">violet <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>; magenta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>; grey <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8797"</span></span>
<span id="cb1-10">theme_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>),</span>
<span id="cb1-12">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
</details>
</div>
<p>You have two genotypes, a treatment, and RNA-seq counts from every combination. Which genes respond to the treatment differently in the two genotypes? A common answer is to analyse each genotype on its own and call a gene “genotype-specific” when it is significant in one analysis and not in the other. The correct answer is a single model with an interaction term, <code>~ genotype + treatment + genotype:treatment</code>, and a test of the interaction coefficient. In the simulation below, the two-list approach labels 29% of the genes that respond identically in both genotypes as genotype-specific, and 29.3% of all its genotype-specific calls are genes with no true difference in response. For the interaction test that share is 5.1%, about the 5% target.</p>
<section id="what-the-interaction-coefficient-is" class="level2">
<h2 class="anchored" data-anchor-id="what-the-interaction-coefficient-is">What the interaction coefficient is</h2>
<p>The experiment has two factors with two levels each: genotype A or B, control or treated. That gives four groups of samples. DESeq2 fits a negative binomial generalised linear model to each gene; its coefficients are on the log2 scale, so each one other than the intercept is a log2 fold change (Love et al.&nbsp;2014). With the interaction in the design formula there are four coefficients for the four group means:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">cd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">genotype  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)),</span>
<span id="cb2-2">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">treatment =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)))</span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(cd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype, cd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>treatment)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>   
    ctrl trt
  A    3   3
  B    3   3</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> treatment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> genotype<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>treatment, cd))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "(Intercept)"            "genotypeB"              "treatmenttrt"          
[4] "genotypeB:treatmenttrt"</code></pre>
</div>
</div>
<p>Read them with genotype A and control as the reference levels (the first level of each factor). The intercept is the log2 mean of untreated genotype A. <code>genotypeB</code> is the difference between the genotypes in untreated samples. <code>treatmenttrt</code> is the treatment effect <em>in genotype A only</em>, not an average over genotypes; the DESeq2 vignette calls this the key point to remember about designs with interaction terms. The interaction, <code>genotypeB:treatmenttrt</code>, is the treatment effect in genotype B minus the treatment effect in genotype A. A gene that goes up fourfold with treatment in A (log2 fold change 2) and twofold in B (log2 fold change 1) has an interaction of minus 1. The treatment effect in B is the sum of the treatment coefficient and the interaction.</p>
<p>So the interaction coefficient answers exactly the question “does the treatment response differ between genotypes?”, and its test is the test of that question. The figure shows the three patterns used below.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">ex <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand.grid</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">treatment =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">genotype =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>),</span>
<span id="cb6-2">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal effect"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opposite"</span>))</span>
<span id="cb6-3">slope <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal effect"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A only"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opposite"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># effect in B for an effect of 1 in A</span></span>
<span id="cb6-4">ex<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (ex<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (ex<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>treatment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(ex<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, slope[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(ex<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>type)])</span>
<span id="cb6-6">lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(slope), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(ex<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>type)),</span>
<span id="cb6-7">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">txt =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"interaction ="</span>, slope <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb6-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(ex, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(treatment, log2mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> genotype, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> genotype)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> lab, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> txt), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inherit.aes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb6-11">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey30"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> type) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">6.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9.2</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">A =</span> violet, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">B =</span> magenta)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true log2 mean"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-meaning" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three panels of line plots on a log2 mean scale. In the equal effect panel the lines for genotype A and genotype B rise in parallel. In the A only panel the genotype A line rises and the genotype B line is flat. In the opposite panel the genotype A line rises and the genotype B line falls by the same amount.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-meaning-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/interaction-terms-deseq2/index_files/figure-html/fig-meaning-1.png" class="img-fluid figure-img" alt="Three panels of line plots on a log2 mean scale. In the equal effect panel the lines for genotype A and genotype B rise in parallel. In the A only panel the genotype A line rises and the genotype B line is flat. In the opposite panel the genotype A line rises and the genotype B line falls by the same amount." width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-meaning-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Schematic of the three kinds of treatment response in the simulation (illustrative values). Each panel is one gene type; lines join the control and treated means of each genotype. The interaction coefficient is the difference between the two slopes.
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="the-simulation" class="level2">
<h2 class="anchored" data-anchor-id="the-simulation">The simulation</h2>
<p>Each simulated experiment has twelve samples, three per group, and 3,000 genes. Counts are negative binomial, the usual model for RNA-seq read counts, with more scatter for weakly expressed genes. Every gene gets its own baseline level and a random baseline difference between the genotypes. The genes fall into four types:</p>
<ul>
<li>1,800 genes do not respond to the treatment in either genotype;</li>
<li>400 respond with the same log2 fold change in both genotypes;</li>
<li>400 respond in genotype A and not at all in B;</li>
<li>400 respond in A and by the same amount in the opposite direction in B.</li>
</ul>
<p>For the responding genes the size of the log2 fold change is drawn between 0.6 and 1.4, with a random sign. Only the last two types have a true interaction.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">G <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3000</span></span>
<span id="cb7-2">n_cls <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">null =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1800</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">equal =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">A_only =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">opposite =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>)</span>
<span id="cb7-3">cls <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(n_cls), n_cls), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(n_cls))</span>
<span id="cb7-4">lfc_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.4</span>)                               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |log2 fold change| of responding genes</span></span>
<span id="cb7-5">sim_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb7-6">  mu0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(G, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.3</span>))                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline mean count</span></span>
<span id="cb7-7">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(G, lfc_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], lfc_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), G, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb7-8">  bA <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(cls <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, d)                    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># treatment effect in genotype A</span></span>
<span id="cb7-9">  bB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(cls <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A_only"</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># treatment effect in genotype B</span></span>
<span id="cb7-10">               <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(cls <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>, d, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>d))</span>
<span id="cb7-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu0 =</span> mu0, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.03</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(mu0),        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NB dispersion, higher for low counts</span></span>
<span id="cb7-12">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bA =</span> bA, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bB =</span> bB, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gx =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(G, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>))        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># gx: genotype B baseline shift</span></span>
<span id="cb7-13">}</span>
<span id="cb7-14">sim_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(g) {</span>
<span id="cb7-15">  isB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>; isT <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>treatment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span></span>
<span id="cb7-16">  lf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>gx, isB) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bA, isT <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>isB) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bB, isT <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> isB)</span>
<span id="cb7-17">  mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu0 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>lf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.25</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> G)</span>
<span id="cb7-18">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(G <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>phi), G, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span>
<span id="cb7-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">storage.mode</span>(m) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"integer"</span></span>
<span id="cb7-20">  m</span>
<span id="cb7-21">}</span></code></pre></div></div>
</div>
<p>The size of the problem shown below depends on power, the chance that a truly responding gene reaches significance. If power were close to 1 or close to 0, the two-list approach would rarely split a gene. It does the most damage in between, which is where this three-replicate experiment with moderate effects sits. The other assumptions (balanced groups, effects that add on the log scale, a correct count model) are shared by both analyses.</p>
<p>Each dataset is analysed in two ways, both with the DESeq2 standard workflow (<code>DESeq()</code>, then <code>results()</code> at a 5% false discovery rate, FDR, with its <code>alpha</code> argument set to that cut-off as the vignette asks whenever the cut-off differs from the default). The first fits one model to all twelve samples and tests the interaction coefficient. The second splits the samples by genotype, fits <code>~ treatment</code> to each half, and compares the two lists of significant genes, which is what a Venn diagram of the two lists does.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">alpha <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>                                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># FDR cut-off</span></span>
<span id="cb8-2">sig <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(r) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(r<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> r<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha</span>
<span id="cb8-3">analyse <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(cts) {</span>
<span id="cb8-4">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one model with the interaction</span></span>
<span id="cb8-5">  dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(cts, cd, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> treatment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> genotype<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>treatment),</span>
<span id="cb8-6">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb8-7">  inter <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB.treatmenttrt"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> alpha)</span>
<span id="cb8-8">  inA   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> alpha)</span>
<span id="cb8-9">  inB   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB.treatmenttrt"</span>)),</span>
<span id="cb8-10">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> alpha)</span>
<span id="cb8-11">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># two separate analyses, one per genotype</span></span>
<span id="cb8-12">  sep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">A =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">B =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) {</span>
<span id="cb8-13">    s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k</span>
<span id="cb8-14">    d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(cts[, s], cd[s, ], <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> treatment), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb8-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> alpha)</span>
<span id="cb8-16">  })</span>
<span id="cb8-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dds =</span> dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inter =</span> inter, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inA =</span> inA, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inB =</span> inB, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sepA =</span> sep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>A, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sepB =</span> sep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>B)</span>
<span id="cb8-18">}</span></code></pre></div></div>
</div>
<p>The loop repeats the whole experiment 5 times with new genes and new counts. For every repeat it records, per gene type, the share of genes each approach calls genotype-dependent.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">n_rep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb9-3">rates <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>()</span>
<span id="cb9-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (r <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_rep)) {</span>
<span id="cb9-5">  g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_genes</span>()</span>
<span id="cb9-6">  cts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_counts</span>(g)</span>
<span id="cb9-7">  a <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">analyse</span>(cts)</span>
<span id="cb9-8">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (r <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) { g1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> g; cts1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cts; a1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> a }</span>
<span id="cb9-9">  sA <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepA); sB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepB)</span>
<span id="cb9-10">  venn  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xor</span>(sA, sB)                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># significant in one genotype only</span></span>
<span id="cb9-11">  venn1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inA), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inB))         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the same, from the one-model contrasts</span></span>
<span id="cb9-12">  inter <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inter)</span>
<span id="cb9-13">  diff_true <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bA <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bB</span>
<span id="cb9-14">  rates[[r]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rep =</span> r, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">class =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(cls),</span>
<span id="cb9-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">venn  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(venn, cls, mean), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">venn1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(venn1, cls, mean),</span>
<span id="cb9-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inter =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(inter, cls, mean), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">both =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(sA <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sB, cls, mean),</span>
<span id="cb9-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sigA =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(sA, cls, mean), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sigB =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(sB, cls, mean),</span>
<span id="cb9-18">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_venn =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>diff_true[venn]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_venn1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>diff_true[venn1]),</span>
<span id="cb9-19">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_inter =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>diff_true[inter]), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_venn =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(venn), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_inter =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(inter),</span>
<span id="cb9-20">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se_ratio =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inter<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfcSE <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inA<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfcSE, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>))</span>
<span id="cb9-21">}</span>
<span id="cb9-22">rates <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, rates)</span></code></pre></div></div>
</div>
</section>
<section id="two-lists-and-a-venn-diagram" class="level2">
<h2 class="anchored" data-anchor-id="two-lists-and-a-venn-diagram">Two lists and a Venn diagram</h2>
<div class="cell">
<details class="code-fold">
<summary>Summarise the repeats</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">avg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aggregate</span>(. <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> class, rates[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setdiff</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(rates), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rep"</span>)], mean)</span>
<span id="cb10-2">v <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(cl, col) avg[avg<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> cl, col]</span>
<span id="cb10-3">venn_eq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"venn"</span>); venn1_eq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"venn1"</span>); inter_eq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inter"</span>)</span>
<span id="cb10-4">sigA_eq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigA"</span>); sigB_eq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigB"</span>)</span>
<span id="cb10-5">venn_null <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"venn"</span>); inter_null <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inter"</span>)</span>
<span id="cb10-6">venn_Aonly <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A_only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"venn"</span>); inter_Aonly <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A_only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inter"</span>)</span>
<span id="cb10-7">both_opp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opposite"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"both"</span>); venn_opp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opposite"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"venn"</span>); inter_opp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opposite"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inter"</span>)</span>
<span id="cb10-8">fdp_venn <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp_venn"</span>); fdp_venn1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp_venn1"</span>); fdp_inter <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp_inter"</span>)</span>
<span id="cb10-9">n_venn <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_venn"</span>); n_inter <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_inter"</span>)</span>
<span id="cb10-10">se_ratio <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"se_ratio"</span>)</span>
<span id="cb10-11">venn_eq_rng <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>venn[rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span>])</span>
<span id="cb10-12">fdp_venn_rng <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp_venn[rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>])</span>
<span id="cb10-13">fdp_inter_rng <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp_inter[rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>])</span>
<span id="cb10-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># design factor: variance of the interaction vs a within-genotype treatment effect</span></span>
<span id="cb10-15">X <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> treatment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> genotype<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>treatment, cd)</span>
<span id="cb10-16">XtXi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">solve</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">crossprod</span>(X))</span>
<span id="cb10-17">se_design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(XtXi[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB:treatmenttrt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB:treatmenttrt"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span></span>
<span id="cb10-18">                  XtXi[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatmenttrt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatmenttrt"</span>])</span>
<span id="cb10-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># first simulated experiment: equal-effect genes significant in one genotype only</span></span>
<span id="cb10-20">eq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cls <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal"</span></span>
<span id="cb10-21">sA1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepA); sB1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepB)</span>
<span id="cb10-22">lA1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepA<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange; lB1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange</span>
<span id="cb10-23">one <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> eq <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">xor</span>(sA1, sB1)</span>
<span id="cb10-24">n_one <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(one)</span>
<span id="cb10-25">n_one_inter <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sig</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inter)[one])                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># of these, flagged by the interaction test</span></span>
<span id="cb10-26">side_share <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(sA1, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lA1) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lB1), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lB1) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lA1))[one])</span>
<span id="cb10-27">gap_one  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lA1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lB1)[one])</span>
<span id="cb10-28">gap_both <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lA1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lB1)[eq <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sA1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sB1])</span>
<span id="cb10-29">avg</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>     class       venn      venn1      inter         both       sigA   sigB
1   A_only 0.69700000 0.71200000 0.42150000 0.0080000000 0.70350000 0.0095
2    equal 0.29000000 0.27400000 0.00750000 0.5335000000 0.70250000 0.6545
3     null 0.02588889 0.02988889 0.01355556 0.0002222222 0.01633333 0.0100
4 opposite 0.28250000 0.26750000 0.86200000 0.5350000000 0.69900000 0.6535
   fdp_venn fdp_venn1  fdp_inter n_venn n_inter se_ratio
1 0.2927728 0.2941584 0.05077606  554.4   540.8 1.415617
2 0.2927728 0.2941584 0.05077606  554.4   540.8 1.415617
3 0.2927728 0.2941584 0.05077606  554.4   540.8 1.415617
4 0.2927728 0.2941584 0.05077606  554.4   540.8 1.415617</code></pre>
</div>
<details class="code-fold">
<summary>Summarise the repeats</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aggregate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(venn, inter) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> class, rates, range)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># min and max over repeats</span></span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>     class     venn.1     venn.2    inter.1    inter.2
1   A_only 0.66750000 0.74750000 0.38750000 0.45000000
2    equal 0.26000000 0.31000000 0.00250000 0.01000000
3     null 0.01555556 0.03333333 0.01166667 0.01555556
4 opposite 0.26750000 0.31250000 0.83750000 0.87750000</code></pre>
</div>
<details class="code-fold">
<summary>Summarise the repeats</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se_design =</span> se_design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se_ratio =</span> se_ratio, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_venn_rng =</span> fdp_venn_rng, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp_inter_rng =</span> fdp_inter_rng)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>     se_design       se_ratio  fdp_venn_rng1  fdp_venn_rng2 fdp_inter_rng1 
    1.41421356     1.41561660     0.26728972     0.30598291     0.04332130 
fdp_inter_rng2 
    0.05950096 </code></pre>
</div>
<details class="code-fold">
<summary>Summarise the repeats</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_one =</span> n_one, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_one_inter =</span> n_one_inter, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">side_share =</span> side_share,</span>
<span id="cb16-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gap_one =</span> gap_one, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gap_both =</span> gap_both)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>      n_one n_one_inter  side_share     gap_one    gap_both 
104.0000000   1.0000000   0.9807692   0.4673976   0.2340765 </code></pre>
</div>
</div>
<p>In the separate analyses, 70% of the equal-effect genes are significant in genotype A and 65% in genotype B. Those are two imperfect detectors pointed at the same signal, and they often disagree: 29% of the equal-effect genes are significant in exactly one genotype (between 26% and 31% across the repeats), and a Venn diagram puts every one of them in a genotype-specific segment. The next figure shows these genes for the first simulated experiment.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">lab_v <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(sA1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sB1, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"both"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(sA1, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A only"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(sB1, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"neither"</span>)))</span>
<span id="cb18-2">sc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lA =</span> a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepA<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lB =</span> a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sepB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange,</span>
<span id="cb18-3">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">venn =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lab_v, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"both"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"neither"</span>)))[eq, ]</span>
<span id="cb18-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(sc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(lA, lB, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> venn)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_abline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">slope =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">intercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey60"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">both =</span> grey, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A only"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B only"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta,</span>
<span id="cb18-8">                                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">neither =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey85"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"significant in"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_equal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"estimated log2 fold change, genotype A"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"estimated log2 fold change, genotype B"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-11">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-scatter" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Scatter plot of estimated log2 fold change in genotype B against genotype A. The points form two clouds along the diagonal, one for up and one for down responses. Points significant in both genotypes are grey. Violet points, significant in genotype A only, sit on the genotype A side of the diagonal, and magenta points, significant in genotype B only, on the genotype B side, at the edges of the same clouds as the grey points.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-scatter-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/interaction-terms-deseq2/index_files/figure-html/fig-scatter-1.png" class="img-fluid figure-img" alt="Scatter plot of estimated log2 fold change in genotype B against genotype A. The points form two clouds along the diagonal, one for up and one for down responses. Points significant in both genotypes are grey. Violet points, significant in genotype A only, sit on the genotype A side of the diagonal, and magenta points, significant in genotype B only, on the genotype B side, at the edges of the same clouds as the grey points." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-scatter-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Estimated treatment log2 fold changes from the two separate analyses, for the genes whose true effect is the same in both genotypes (first simulated experiment). Colour shows the Venn label; the diagonal is equal effect.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The coloured points are not spread at random. Genes called in genotype A only sit on the A side of the diagonal, with a larger estimated effect in A than in B, and genes called in B only sit on the B side; in this experiment that holds for 98% of them. They form the edges of the same clouds as the grey genes. That is selection, not biology. A gene lands in the A-only segment when noise pushes its estimate in A over the significance threshold and its estimate in B below it, so the genes in that segment are the ones whose two estimates happened to drift apart. The median gap between the two estimated log2 fold changes is 0.47 for the genes significant in one genotype only, against 0.23 for the genes significant in both.</p>
<p>A reader looking at the figure could take that wider gap as evidence of a different response. It is not: the true effects are identical, and the gap is no larger than the noise in two separate estimates produces. The interaction test, which asks exactly whether the two effects differ, flags 1 of the 104 genes in this experiment that the Venn diagram puts in a genotype-specific segment. Gelman and Stern (2006) put the general point in their title: the difference between “significant” and “not significant” is not itself statistically significant. A non-significant result in genotype B means the data could not show an effect there, not that there is none.</p>
<p>The error is not caused by fitting the two genotypes separately. Taking the two per-genotype effects from the single interaction model (shown further down) and comparing their significance calls in the same way labels 27% of the equal-effect genes as genotype-specific, and 29% of those calls are false. The problem is the comparison of two significance calls, wherever they come from.</p>
<p>The two-list approach also mislabels many of the most striking genes. Of the genes that respond in opposite directions, 54% are significant in both analyses. In a Venn diagram of gene identifiers they sit in the shared segment, as “responds in both genotypes”, although the response is reversed. Only 28% of them are called genotype-specific. Splitting the lists by direction of change catches these genes, but not the equal-effect problem above.</p>
</section>
<section id="the-interaction-test" class="level2">
<h2 class="anchored" data-anchor-id="the-interaction-test">The interaction test</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1">long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(rates[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rep"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"class"</span>)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Venn of two analyses"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>venn),</span>
<span id="cb19-2">              <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(rates[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rep"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"class"</span>)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"interaction test"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> rates<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inter))</span>
<span id="cb19-3">long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(cls)),</span>
<span id="cb19-4">                     <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"equal effect"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A only"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opposite"</span>)))</span>
<span id="cb19-5">long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"interaction test"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>)</span>
<span id="cb19-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(value, y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> method)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb19-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb19-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Venn of two analyses"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"interaction test"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet),</span>
<span id="cb19-9">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb19-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>class)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb19-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb19-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"share of genes called genotype-dependent"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-rates" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Dot plot with four gene types on the vertical axis and two methods. For null genes both methods call almost none. For equal effect genes the Venn approach calls a large share genotype-dependent while the interaction test calls almost none. For A only genes the Venn approach calls more than the interaction test. For opposite genes the interaction test calls most of them and the Venn approach under a third.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-rates-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/interaction-terms-deseq2/index_files/figure-html/fig-rates-1.png" class="img-fluid figure-img" alt="Dot plot with four gene types on the vertical axis and two methods. For null genes both methods call almost none. For equal effect genes the Venn approach calls a large share genotype-dependent while the interaction test calls almost none. For A only genes the Venn approach calls more than the interaction test. For opposite genes the interaction test calls most of them and the Venn approach under a third." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-rates-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Share of genes called genotype-dependent by the Venn approach (significant in one separate analysis only) and by the interaction test (adjusted p below the FDR cut-off), by true response type. Each dot is one simulated experiment.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The interaction test calls 0.8% of the equal-effect genes and 1.4% of the non-responding genes genotype-dependent. Among all genes it calls, 5.1% have no true interaction on average (between 4.3% and 6.0% across the repeats), about the 5% target it was run at (a little above it in some repeats). For the two-list approach the same share is 29.3% on average. Both lists are about the same length, 541 genes for the interaction test and 554 for the Venn approach; they differ in what is on them. The interaction test also finds 86% of the opposite-direction genes.</p>
<p>There is a cost, and the figure shows it. For genes that respond in genotype A only, the interaction test finds 42%, while the two-list approach labels 70% of them genotype-specific. That is not extra power in the two-list approach. It applies a lower bar (significant in one genotype, not in the other), and the same lower bar is what mislabels the equal-effect genes; a list that cannot tell you which 29.3% of its entries are wrong is not a better list.</p>
<p>The interaction really is harder to estimate than a single treatment effect. It is a difference between two differences, each estimated from six samples, so its variance is the sum of theirs. In this balanced design the standard error of the interaction coefficient is 1.41 times that of the treatment effect in one genotype (the square root of 2, from the design matrix alone); the median ratio of the standard errors DESeq2 reports is 1.42. To detect a given difference in response with the same power as a response of the same size within one genotype, the sample size has to grow by a factor of about 2, and by more if the difference in response you care about is smaller than the response itself. If a genotype-dependent response is the main question of the experiment, that belongs in the sample size calculation.</p>
</section>
<section id="the-treatment-effect-in-each-genotype" class="level2">
<h2 class="anchored" data-anchor-id="the-treatment-effect-in-each-genotype">The treatment effect in each genotype</h2>
<p>Often you want the per-genotype effects as well, for example to report a fold change for each genotype next to the interaction test. All of them come from the one model. The names DESeq2 gives the coefficients differ from the model matrix column names (the main effects are renamed and the colon becomes a dot), so read them off <code>resultsNames()</code> rather than typing them from memory:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resultsNames</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dds)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Intercept"              "genotype_B_vs_A"        "treatment_trt_vs_ctrl" 
[4] "genotypeB.treatmenttrt"</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># argument names used below</span></span>
<span id="cb22-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contrast"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"alpha"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(results))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] TRUE TRUE TRUE</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(results)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>alpha                                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># default FDR target of results()</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.1</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"reduced"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] TRUE TRUE</code></pre>
</div>
</div>
<p>The treatment effect in genotype A is the coefficient <code>treatment_trt_vs_ctrl</code>, extracted with <code>results(dds, name = "treatment_trt_vs_ctrl")</code>. The effect in genotype B is that coefficient plus the interaction. <code>results()</code> accepts a list for its <code>contrast</code> argument; according to its help page the first element names the coefficients that are added up for the numerator, and a list of length one is completed with an empty denominator. This is the route shown in Examples 2 and 3 of the <code>results()</code> help page:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb28-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB.treatmenttrt"</span>)))</span></code></pre></div></div>
<p>The chunk below checks it three ways on the first simulated dataset: against the sum of the two fitted coefficients, against a refit with genotype B as the reference level, and against the combined-factor design (<code>~ group</code>, with levels such as <code>Bctrl</code> and <code>Btrt</code>) that the DESeq2 vignette suggests when only per-group comparisons are wanted.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb29-1">b <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coef</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dds)                                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># MLE coefficients, log2 scale</span></span>
<span id="cb29-2">sum_coef <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> b[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> b[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB.treatmenttrt"</span>]</span>
<span id="cb29-3">diff_sum <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> sum_coef), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb29-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the same effect with genotype B as the reference level</span></span>
<span id="cb29-5">dds_B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dds</span>
<span id="cb29-6">dds_B<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">relevel</span>(dds_B<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>)</span>
<span id="cb29-7">dds_B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds_B, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb29-8">rB_relevel <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds_B, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>)</span>
<span id="cb29-9">diff_relevel <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> rB_relevel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb29-10">diff_relevel_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> rB_relevel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb29-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the combined-factor route from the vignette</span></span>
<span id="cb29-12">dds_g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dds</span>
<span id="cb29-13">dds_g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(dds_g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype, dds_g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>treatment))</span>
<span id="cb29-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">design</span>(dds_g) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">~</span> group</span>
<span id="cb29-15">dds_g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds_g, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb29-16">rB_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds_g, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Btrt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bctrl"</span>))</span>
<span id="cb29-17">diff_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> rB_group<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb29-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the interaction as a single contrast in the ~ group design</span></span>
<span id="cb29-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resultsNames</span>(dds_g)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Intercept"            "group_Atrt_vs_Actrl"  "group_Bctrl_vs_Actrl"
[4] "group_Btrt_vs_Actrl" </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb31-1">int_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds_g, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_Btrt_vs_Actrl"</span>,</span>
<span id="cb31-2">                                            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_Bctrl_vs_Actrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_Atrt_vs_Actrl"</span>)))</span>
<span id="cb31-3">diff_int_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inter<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> int_group<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb31-4">diff_int_group_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(a1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>inter<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> int_group<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb31-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diff_sum =</span> diff_sum, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diff_relevel =</span> diff_relevel, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diff_relevel_p =</span> diff_relevel_p,</span>
<span id="cb31-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diff_group =</span> diff_group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diff_int_group =</span> diff_int_group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diff_int_group_p =</span> diff_int_group_p)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>        diff_sum     diff_relevel   diff_relevel_p       diff_group 
    4.440892e-16     4.758795e-06     1.483779e-06     7.719630e-06 
  diff_int_group diff_int_group_p 
    1.710804e-05     9.779561e-07 </code></pre>
</div>
</div>
<p>The list contrast equals the sum of the coefficients to machine precision (largest difference 4e-16). The refit with genotype B as reference and the combined-factor design give the same log2 fold changes up to the tolerance of the fitting algorithm (largest differences 5e-06 and 8e-06), and the relevelled fit gives the same p-values to within 1e-06.</p>
<p>The <code>~ group</code> design does not take the interaction test away, although its separate per-group tables invite the Venn comparison. The interaction is the treated-minus-control difference in B minus the same difference in A, which is one list contrast of the group coefficients:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb33-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds_g, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_Btrt_vs_Actrl"</span>,</span>
<span id="cb33-2">                               <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_Bctrl_vs_Actrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_Atrt_vs_Actrl"</span>)))</span></code></pre></div></div>
<p>In the chunk above it reproduces the interaction coefficient of the first model (largest difference in log2 fold change 2e-05, in p-value 1e-06).</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>When the question is whether a response differs between groups, put that question into the design formula and test the coefficient that answers it. This is the same rule as for batch effects (see <a href="https://pseudocount.com/posts/confounded-batch-and-condition/">the post on confounded batches</a>): the comparison belongs in the model, not in a comparison of two results tables after the fact.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(counts, samples,</span>
<span id="cb34-2">                              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> genotype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> treatment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> genotype<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>treatment)</span>
<span id="cb34-3">dds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">relevel</span>(dds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>)      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># set reference levels before DESeq()</span></span>
<span id="cb34-4">dds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>treatment <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">relevel</span>(dds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>treatment, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>)</span>
<span id="cb34-5">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds)</span>
<span id="cb34-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resultsNames</span>(dds)</span>
<span id="cb34-7"></span>
<span id="cb34-8">res_diff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB.treatmenttrt"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># does the response differ?</span></span>
<span id="cb34-9">res_A    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># response in genotype A</span></span>
<span id="cb34-10">res_B    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>,</span>
<span id="cb34-11">                                           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genotypeB.treatmenttrt"</span>)),</span>
<span id="cb34-12">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)                                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># response in genotype B</span></span></code></pre></div></div>
<p>Report genes as genotype-dependent only when <code>res_diff</code> calls them, and show the two per-genotype fold changes side by side, with their standard errors, rather than as a Venn diagram. For plotting or ranking those fold changes, the DESeq2 vignette recommends shrunken estimates from <code>lfcShrink()</code>. Its default <code>apeglm</code> method needs a coefficient name (<code>coef</code>) rather than a contrast, so the effect in genotype B comes from a fit with B as the reference level:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb35-1">shr_A <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lfcShrink</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># apeglm package required</span></span>
<span id="cb35-2">dds_B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> dds</span>
<span id="cb35-3">dds_B<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">relevel</span>(dds_B<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>genotype, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>)</span>
<span id="cb35-4">dds_B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds_B)</span>
<span id="cb35-5">shr_B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lfcShrink</span>(dds_B, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treatment_trt_vs_ctrl"</span>)</span></code></pre></div></div>
<p>With more than two genotypes, a likelihood ratio test asks whether the response differs anywhere: <code>DESeq(dds, test = "LRT", reduced = ~ genotype + treatment)</code>. A gene significant in one genotype and not in the other has not been shown to be genotype-specific; it may only have been measured with less certainty in one of them.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<p>Gelman A, Stern H 2006 The American Statistician 60(4):328-331 (<a href="https://doi.org/10.1198/000313006X152649">doi:10.1198/000313006X152649</a>)</p>
<p>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</p>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, generics 0.1.4,
GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0, MatrixGenerics
1.22.0, matrixStats 1.5.0, S4Vectors 0.48.1, Seqinfo 1.0.0,
SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>DESeq2</category>
  <category>RNA-seq</category>
  <category>experimental design</category>
  <category>interaction terms</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/interaction-terms-deseq2/</guid>
  <pubDate>Mon, 14 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/interaction-terms-deseq2/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Independent filtering: when gene filters break the FDR</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/independent-filtering-fdr/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-5">})</span>
<span id="cb1-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.36"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>,</span>
<span id="cb1-7">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4.0"</span>)</span>
<span id="cb1-8"></span>
<span id="cb1-9">pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f%%"</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-10">num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trim =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-11">dec <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>), x)</span>
<span id="cb1-12"></span>
<span id="cb1-13">fdr_level <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># genes are called at this Benjamini-Hochberg adjusted p-value</span></span>
<span id="cb1-14"></span>
<span id="cb1-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Benjamini-Hochberg on the genes in `keep` only; the rest stay missing</span></span>
<span id="cb1-16">bh_on <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, keep) {</span>
<span id="cb1-17">  padj <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA_real_</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(p))</span>
<span id="cb1-18">  ok <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(p)</span>
<span id="cb1-19">  padj[ok] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(p[ok], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>)</span>
<span id="cb1-20">  padj</span>
<span id="cb1-21">}</span>
<span id="cb1-22"></span>
<span id="cb1-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what we can measure because the truth is known</span></span>
<span id="cb1-24">score <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(padj, is_de) {</span>
<span id="cb1-25">  call <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(padj) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> fdr_level</span>
<span id="cb1-26">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_call =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(call),</span>
<span id="cb1-27">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(call)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de[call]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># false discovery proportion</span></span>
<span id="cb1-28">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">power =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(call <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> is_de) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(is_de))            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># share of ALL changed genes found</span></span>
<span id="cb1-29">}</span>
<span id="cb1-30"></span>
<span id="cb1-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the defaults this post talks about, read from the installed packages</span></span>
<span id="cb1-32">results_alpha <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>results)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>alpha)</span>
<span id="cb1-33">results_indep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>results)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>independentFiltering)</span>
<span id="cb1-34">results_althyp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>results)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>altHypothesis)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb1-35">fbe_min_count <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>filterByExpr.default)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>min.count)</span>
<span id="cb1-36">fbe_min_total <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>filterByExpr.default)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>min.total.count)</span></code></pre></div></div>
</details>
</div>
<p>You have a results table with a few thousand genes, many of them barely expressed, and you would like to drop the uninteresting ones before correcting for multiple testing. Is that allowed? Yes, if the filter ignores which sample is in which group and is (approximately) independent of the test for genes that do not change, as the mean count is; no, if it looks at the groups. In the simulation below, filtering on expression kept the realised false discovery rate (FDR) at 4.7% with edgeR and 4.7% with DESeq2’s automatic filter, for a nominal 5%, and DESeq2’s filter called 6.0% more genes than no filter at all. Keeping only genes with at least a 1.4-fold difference between the groups before the correction pushed the realised FDR to 16.4%.</p>
<section id="why-removing-genes-can-add-power" class="level2">
<h2 class="anchored" data-anchor-id="why-removing-genes-can-add-power">Why removing genes can add power</h2>
<p>The usual FDR correction is the Benjamini-Hochberg procedure (Benjamini and Hochberg 1995). It sorts the p-values of all tested genes and compares the k-th smallest with k/m times the target FDR, where m is the number of genes tested. The larger m is, the higher the bar every gene has to clear. In RNA-seq a large share of genes have so few reads that they could never produce a small p-value, whatever their true change, yet each of them adds to m. Removing them before the correction lowers the bar for the rest. (The same genes bend the p-value histogram towards 1, as shown in <a href="https://pseudocount.com/posts/p-value-histogram-diagnostics/">the post on p-value histograms</a>; here the question is what removing them does to the FDR.)</p>
<p>The catch is in how you choose which genes to remove. The procedure’s guarantee rests on the p-values of null genes, genes with no true change, being spread evenly between 0 and 1. Bourgon, Gentleman and Huber (2010) showed that filtering keeps this property when, for null genes, the filter statistic is independent of the test statistic. The overall mean count, computed across all samples without looking at the group labels, is the standard example. A statistic that looks at the difference between the groups is not: a null gene whose groups differ by chance has both a large difference and a small p-value, so a filter on the difference hands the correction a set of null genes with too many small p-values. The simulation below measures both.</p>
</section>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>Each simulated experiment has 3,000 genes measured in 4 control and 4 treated samples, with counts drawn from a negative binomial distribution (the standard model for RNA-seq counts, in which the variance grows faster than the mean). Mean counts are spread over several orders of magnitude, so that 49% of genes average fewer than 10 reads per sample, much as in a real annotation with many barely expressed genes. The dispersion, the biological part of the variance, is larger for weakly expressed genes. In each experiment 15% of genes truly change, with a log2 fold change between 0.5 and 2 in either direction; the rest are null.</p>
<p>I simulate 16 experiments and report averages over them, because the FDR is itself an average over experiments: in a single experiment the share of false calls can land above the target without anything being wrong.</p>
<p>Two assumptions deserve a flag. Genes are simulated independently of each other, while real genes are correlated. And the share of changed genes and the size of their changes are my choices; the last section shows that the damage done by a bad filter depends on the first.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">n_per <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>                                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># samples per condition</span></span>
<span id="cb2-2">n_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3000</span>                              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># genes per experiment</span></span>
<span id="cb2-3">n_exp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>                                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># simulated experiments</span></span>
<span id="cb2-4">de_frac <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>                              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># share of genes that truly change</span></span>
<span id="cb2-5">lfc_min <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>; lfc_max <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># size of true changes, |log2 fold change|</span></span>
<span id="cb2-6">group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n_per))</span>
<span id="cb2-7">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb2-8"></span>
<span id="cb2-9">simulate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(n_rows, de_frac, n_block) {</span>
<span id="cb2-10">  mu0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_rows, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>))                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># mean count, most genes low</span></span>
<span id="cb2-11">  phi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(mu0 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_rows, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># dispersion</span></span>
<span id="cb2-12">  is_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_block) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> de_frac <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_block, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> n_rows)</span>
<span id="cb2-13">  lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(is_de, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), n_rows, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n_rows, lfc_min, lfc_max), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb2-14">  size_factor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>))</span>
<span id="cb2-15">  mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(mu0, size_factor) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(lfc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>))</span>
<span id="cb2-16">  counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(mu), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_rows)</span>
<span id="cb2-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">counts =</span> counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> lfc)</span>
<span id="cb2-18">}</span>
<span id="cb2-19"></span>
<span id="cb2-20"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb2-21">sim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate</span>(n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_exp, de_frac, n_genes)</span>
<span id="cb2-22">experiment <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_exp), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n_genes)</span></code></pre></div></div>
</div>
<p>DESeq2 runs its standard workflow, <code>DESeq()</code> then <code>results()</code> (Love, Huber and Anders 2014). To save time it is run once on all experiments stacked on top of each other; they share the 8 samples’ sequencing depths and the fitted dispersion trend, and every experiment is filtered, corrected and scored on its own. edgeR runs per experiment with the quasi-likelihood recipe of Chen, Lun and Smyth (2016), updated with the current <code>filterByExpr()</code> and <code>normLibSizes()</code>: filter, normalise, then <code>glmQLFit()</code> and <code>glmQLFTest()</code>. The fit uses edgeR’s newer quasi-likelihood method, <code>legacy = FALSE</code>, set explicitly so that older and newer edgeR releases run the same method; this method estimates its own dispersion, so <code>estimateDisp()</code> is not needed.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one DESeq2 fit for all experiments (to save time); each experiment is scored on its own below</span></span>
<span id="cb3-2">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb3-3">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb3-4">res_all <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">independentFiltering =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb3-5">low_count <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb3-6">share_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(res_all<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>baseMean <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> low_count)</span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the edgeR quasi-likelihood recipe, filterByExpr first</span></span>
<span id="cb3-9">run_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, fc_cut) {</span>
<span id="cb3-10">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb3-11">  keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb3-12">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb3-13">  fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">robust =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb3-14">  tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table</span>
<span id="cb3-15">  treat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmTreat</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> fc_cut)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># used in the last section</span></span>
<span id="cb3-16">  p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> p_treat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA_real_</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(counts))</span>
<span id="cb3-17">  p[keep] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue; lfc[keep] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>logFC; p_treat[keep] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> treat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue</span>
<span id="cb3-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> lfc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep =</span> keep, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_treat =</span> p_treat)</span>
<span id="cb3-19">}</span></code></pre></div></div>
</div>
<p>The next chunk scores every analysis in this post on each experiment: DESeq2 with and without its automatic filter, the edgeR recipe, both with a fold-change pre-filter added, and the two threshold tests from the last section.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">fc_cut <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>                                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |log2 fold change| cut-off of the pre-filter</span></span>
<span id="cb4-2">thresholds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cut-offs for the sweep further down</span></span>
<span id="cb4-3"></span>
<span id="cb4-4">per_exp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_exp), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(e) {</span>
<span id="cb4-5">  i <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(experiment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> e)</span>
<span id="cb4-6">  de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de[i]</span>
<span id="cb4-7">  p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> res_all<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[i]</span>
<span id="cb4-8">  fc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(res_all<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange[i])</span>
<span id="cb4-9">  auto <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds[i, ], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> fdr_level)             <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># automatic independent filtering</span></span>
<span id="cb4-10">  auto_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds[i, ])                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same, alpha left at its default</span></span>
<span id="cb4-11">  treat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds[i, ], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfcThreshold =</span> fc_cut, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> fdr_level)</span>
<span id="cb4-12">  ed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_edger</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts[i, ], fc_cut)</span>
<span id="cb4-13">  fc_keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(fc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> fc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> fc_cut</span>
<span id="cb4-14">  below_cut <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> res_all<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>baseMean[i] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(auto)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filterThreshold</span>
<span id="cb4-15">  ed_fc_keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> fc_cut</span>
<span id="cb4-16">  ed_padj <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep)                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># correction first ...</span></span>
<span id="cb4-17">  post_cut <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(cut) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> cut, ed_padj, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA_real_</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... then a fold-change cut</span></span>
<span id="cb4-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb4-19">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rows =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb4-20">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_none   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(p, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), de),</span>
<span id="cb4-21">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_auto   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(auto<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj, de),</span>
<span id="cb4-22">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_fc     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(p, fc_keep), de),</span>
<span id="cb4-23">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger        =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep), de),</span>
<span id="cb4-24">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger_fc     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, ed_fc_keep), de),</span>
<span id="cb4-25">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_treat  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(treat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj, de),</span>
<span id="cb4-26">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger_treat  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_treat, ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep), de)),</span>
<span id="cb4-27">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">auto_default =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(auto_default<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj, de),</span>
<span id="cb4-28">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">post =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">small =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">post_cut</span>(fc_cut), de), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">large =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">post_cut</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), de)),</span>
<span id="cb4-29">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">null_share_fc =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de[ed_fc_keep]),</span>
<span id="cb4-30">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filtered =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(auto<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj)),</span>
<span id="cb4-31">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sweep =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(thresholds, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(t) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb4-32">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(p, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(fc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> fc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> t), de)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>]],</span>
<span id="cb4-33">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> t), de)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>]])),</span>
<span id="cb4-34">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># null p-values that survive each filter, for the histogram</span></span>
<span id="cb4-35">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">null_p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb4-36">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p[ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filter =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"recipe"</span>),</span>
<span id="cb4-37">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p[ed_fc_keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filter =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fold"</span>),</span>
<span id="cb4-38">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> p[fc_keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de],</span>
<span id="cb4-39">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filter =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(below_cut[fc_keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_fold_low"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_fold_high"</span>))),</span>
<span id="cb4-40">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">auto =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (e <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) auto <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>)</span>
<span id="cb4-41">})</span>
<span id="cb4-42"></span>
<span id="cb4-43">tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Reduce</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">+</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rows"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_exp</span>
<span id="cb4-44">auto_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auto_default"</span>)))</span>
<span id="cb4-45">filtered_share <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"filtered"</span>))</span>
<span id="cb4-46">gain <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_auto"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_call"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_none"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_call"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb4-47">fdp_fc_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(per_exp, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rows[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edger_fc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>])</span>
<span id="cb4-48">fdp_recipe <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(per_exp, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rows[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edger"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>])</span>
<span id="cb4-49">n_fc_worse <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(fdp_fc_edger <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> fdp_recipe)</span>
<span id="cb4-50">null_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null_p"</span>))</span>
<span id="cb4-51">null_sig <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(null_p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> fdr_level, null_p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filter, mean)</span>
<span id="cb4-52">deseq_null <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> null_p[null_p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_fold_low"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_fold_high"</span>), ]</span>
<span id="cb4-53">deseq_null_sig <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(deseq_null<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> fdr_level)</span>
<span id="cb4-54">deseq_fc_null_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(deseq_null<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq_fold_low"</span>)</span>
<span id="cb4-55">sweep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Reduce</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">+</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sweep"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_exp</span>
<span id="cb4-56">null_share_fc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null_share_fc"</span>))</span>
<span id="cb4-57">post <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Reduce</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">+</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(per_exp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">[[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"post"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_exp</span>
<span id="cb4-58">auto1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> per_exp[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>auto</span></code></pre></div></div>
</div>
</section>
<section id="filtering-on-expression" class="level2">
<h2 class="anchored" data-anchor-id="filtering-on-expression">Filtering on expression</h2>
<p>DESeq2 filters for you. With the default <code>independentFiltering = TRUE</code>, <code>results()</code> filters on the mean of normalised counts across all samples. It tries a series of cut-offs, counts the genes called at each, and keeps the lowest cut-off whose count comes within one residual standard deviation of the peak of a curve fitted through those counts (this is described in the DESeq2 vignette). Genes below the cut-off keep their p-value, but their adjusted p-value is left empty. The search for the first experiment looks like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">nr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(auto1)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filterNumRej</span>
<span id="cb5-2">lo <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(auto1)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lo.fit)</span>
<span id="cb5-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(nr, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(theta, numRej)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> lo, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(x, y), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8e8c9c"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_vline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xintercept =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(auto1)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filterTheta, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>,</span>
<span id="cb5-7">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"share of genes removed (quantile of the mean normalised count)"</span>,</span>
<span id="cb5-9">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genes called"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb5-12">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-numrej" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Points showing genes called against the share of genes removed. The count rises slightly to a flat plateau over the left half of the axis, then falls steeply over the right half as genes that could be called are removed. A grey smooth curve follows the points, and a dashed vertical line on the rising part, just before the plateau, marks the chosen cut-off.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-numrej-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/independent-filtering-fdr/index_files/figure-html/fig-numrej-1.png" class="img-fluid figure-img" alt="Points showing genes called against the share of genes removed. The count rises slightly to a flat plateau over the left half of the axis, then falls steeply over the right half as genes that could be called are removed. A grey smooth curve follows the points, and a dashed vertical line on the rising part, just before the plateau, marks the chosen cut-off." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-numrej-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: DESeq2’s search for an independent filtering cut-off in the first simulated experiment. Each point is the number of genes called after removing the given share of genes with the lowest mean count; the grey line is the fitted curve and the dashed line marks the chosen cut-off.
</figcaption>
</figure>
</div>
</div>
</div>
<p>In this experiment the chosen cut-off removes the 20% of genes whose mean normalised count is below 1.26. Across all experiments it removed 26% of genes on average. DESeq2 then called 172 genes per experiment against 163 without the filter, and found 36.5% of the truly changed genes instead of 34.9%. The realised FDR was 4.7% with the filter and 3.5% without it, both below the nominal level. The gain is modest in this simulation; how large it is in your data depends on how many genes in the table have too few reads to ever be significant.</p>
<p>One detail matters here. The cut-off is chosen to maximise the calls at the significance level <code>alpha</code>, whose default is 0.1. If you call genes at an adjusted p-value of 0.05, the vignette says to set <code>alpha</code> to that value too. Leaving it at the default made little difference in this simulation (171 against 172 genes called), but it costs nothing to set.</p>
<p>edgeR filters before the model is fitted. <code>filterByExpr()</code> keeps genes with at least <code>min.count</code> reads (default 10, converted to counts per million with the median library size) in at least as many samples as the smallest group, and at least <code>min.total.count</code> reads in total (default 15). It uses the group sizes only to decide how many samples a gene must be expressed in; it counts those samples across all columns, so the result does not depend on which sample sits in which group. With <code>filterByExpr()</code> first, the edgeR recipe had a realised FDR of 4.7% and found 35.5% of the changed genes.</p>
</section>
<section id="filtering-on-a-fold-change" class="level2">
<h2 class="anchored" data-anchor-id="filtering-on-a-fold-change">Filtering on a fold change</h2>
<p>Now the tempting shortcut: keep only genes whose groups differ by at least 1.4-fold (an absolute log2 fold change above 0.5), taken from the same results table, and run the correction on those. Added to the edgeR recipe, this raised the calls from 167 to 223 per experiment and the realised FDR from 4.7% to 16.4%. The false discovery proportion was higher with the fold-change filter in every one of the 16 experiments, ranging from 12.0% to 21.1%.</p>
<p>The reason is visible in the null genes that survive the filter.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">lv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">recipe =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"filterByExpr only"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fold =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"filterByExpr, then |logFC| &gt; cut-off"</span>)</span>
<span id="cb6-2">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> null_p[null_p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(lv), ]</span>
<span id="cb6-3">d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lv[d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filter], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> lv)</span>
<span id="cb6-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(p)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">after_stat</span>(density)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>),</span>
<span id="cb6-6">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> panel) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value of null genes that pass the filter"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"density"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">strip.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>),</span>
<span id="cb6-12">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-nullp" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two histograms of p-values on a density scale. Left: all bars sit close to a dashed horizontal line, a flat shape. Right: the bars nearest zero are several times higher than the dashed line, and the bars shrink to nothing well before the middle of the axis.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-nullp-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/independent-filtering-fdr/index_files/figure-html/fig-nullp-1.png" class="img-fluid figure-img" alt="Two histograms of p-values on a density scale. Left: all bars sit close to a dashed horizontal line, a flat shape. Right: the bars nearest zero are several times higher than the dashed line, and the bars shrink to nothing well before the middle of the axis." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-nullp-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: P-values of null genes that pass each filter, pooled over the simulated experiments, from the edgeR recipe. After filterByExpr alone they are spread evenly (left); after an added fold-change filter they pile up near zero (right). The dashed line is the flat density that null p-values should have.
</figcaption>
</figure>
</div>
</div>
</div>
<p>Among null genes that pass <code>filterByExpr()</code>, 5.1% have a p-value below 0.05, which is what a p-value promises. Among null genes that also pass the fold-change filter, 35.5% do. The correction receives a set of genes with far more small p-values than its null model allows for, and treats the excess as signal.</p>
<p>The same filter on DESeq2’s p-values, applied to all genes, raised the realised FDR from 3.5% to 7.1%. That is a smaller rise, and the reason says something about the mechanism. DESeq2’s fold change for a gene with a handful of reads is very noisy, so many null genes with almost no reads pass a fold-change filter: 48% of the null genes that passed had a mean count below the automatic filter’s cut-off. Only 0.8% of those had a p-value below 0.05, against 16.5% of the better expressed null genes that passed, so the low-count genes dilute the problem without removing it. Overall, 8.9% of the null genes passing this filter had a p-value below 0.05, still more than a p-value promises.</p>
</section>
<section id="the-damage-depends-on-what-you-cannot-see" class="level2">
<h2 class="anchored" data-anchor-id="the-damage-depends-on-what-you-cannot-see">The damage depends on what you cannot see</h2>
<p>Is a larger cut-off safer? The next figure repeats the fold-change filter at several cut-offs and adds a second scenario, simulated the same way except that only 5% of genes truly change.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">de_frac_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a second scenario: fewer genes truly change</span></span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2027</span>)</span>
<span id="cb7-3">sim_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate</span>(n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_exp, de_frac_low, n_genes)</span>
<span id="cb7-4">null_share_fc_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(n_exp)</span>
<span id="cb7-5">fdp_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_exp), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(e) {</span>
<span id="cb7-6">  i <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(experiment <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> e)</span>
<span id="cb7-7">  ed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_edger</span>(sim_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts[i, ], fc_cut)</span>
<span id="cb7-8">  null_share_fc_low[e] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de[i][ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> fc_cut])</span>
<span id="cb7-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(thresholds, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(t)</span>
<span id="cb7-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bh_on</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(ed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> t), sim_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de[i])[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>]])</span>
<span id="cb7-11">})</span>
<span id="cb7-12">sweep_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(fdp_low)</span>
<span id="cb7-13">se_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(fdp_low, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, sd) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(n_exp)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Monte Carlo standard error</span></span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">lv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, %s of genes changed"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(de_frac, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)),</span>
<span id="cb8-2">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, %s of genes changed"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(de_frac, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)),</span>
<span id="cb8-3">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, %s of genes changed"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(de_frac_low, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)))</span>
<span id="cb8-4">sw <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">threshold =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(thresholds, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb8-5">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(sweep[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deseq"</span>, ], sweep[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edger"</span>, ], sweep_low),</span>
<span id="cb8-6">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">analysis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(lv, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(thresholds)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> lv))</span>
<span id="cb8-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(sw, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(threshold, fdr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> analysis)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> fdr_level, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#c9c7d4"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5f5c70"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>), lv), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|log2 fold change| cut-off applied before the correction"</span>,</span>
<span id="cb8-14">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"realised FDR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.direction =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vertical"</span>,</span>
<span id="cb8-17">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb8-18">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-sweep" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with three lines of realised FDR against the fold-change cut-off. All start near a dashed horizontal line at the nominal level, rise over small and moderate cut-offs, and fall back at the largest cut-off. The line for the scenario with fewer changed genes rises highest; the DESeq2 line rises least.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-sweep-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/independent-filtering-fdr/index_files/figure-html/fig-sweep-1.png" class="img-fluid figure-img" alt="Line chart with three lines of realised FDR against the fold-change cut-off. All start near a dashed horizontal line at the nominal level, rise over small and moderate cut-offs, and fall back at the largest cut-off. The line for the scenario with fewer changed genes rises highest; the DESeq2 line rises least." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-sweep-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Realised FDR after a fold-change pre-filter, against the cut-off, averaged over the simulated experiments. The dashed line is the nominal level. The filter pushes the FDR above it over a range of cut-offs, and by how much depends on the share of genes that truly change.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With no cut-off the analyses sit near the nominal level. The edgeR run in the second scenario is slightly above it, at 6.6% with a Monte Carlo standard error of 0.7% (the uncertainty that comes from simulating only 16 experiments). Any cut-off in the middle of the range pushes the FDR up, and the push is larger when fewer genes truly change, because a larger share of what passes the filter is then null: at a cut-off of 0.5, 73% of the genes passing were null in the second scenario against 46% in the first. In the second scenario the realised FDR peaked at 36.5% at a cut-off of 0.75. At the popular two-fold cut-off (log2 fold change 1), edgeR’s realised FDR was 6.2% in the first scenario and 20.5% in the second. At the largest cut-off, 1.5, it falls to 1.9%.</p>
<p>So the harm from a fold-change pre-filter is not a fixed penalty you could correct for. It depends on how many genes truly change (and, by the same logic, on how large the changes are), which is exactly what the experiment is trying to find out. A cut-off that looks harmless on one data set carries no guarantee on the next.</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>Filter on expression, and never on anything that uses the group labels. Ignoring the labels is necessary but not sufficient: Bourgon, Gentleman and Huber (2010) show that some filter and test pairs lose control of false positives even so, so stay with the filters the packages provide, which were checked here: the mean count in DESeq2 and <code>filterByExpr()</code> in edgeR. In DESeq2 that means leaving the automatic filter on and setting <code>alpha</code> to the adjusted p-value cut-off you will use. In edgeR it means running <code>filterByExpr()</code> before fitting.</p>
<p>If you only care about changes above a certain size, put the size into the test rather than into a filter. DESeq2’s <code>results()</code> takes <code>lfcThreshold</code>; with the default <code>altHypothesis = "greaterAbs"</code> it tests whether the absolute log2 fold change is greater than the threshold. edgeR’s <code>glmTreat()</code> does the same for a fitted quasi-likelihood model, based on the TREAT approach of McCarthy and Smyth (2009). Its help page adds a warning: the threshold in the test is not a fold-change cut-off, because a gene needs an observed change well above it to be called, so modest thresholds such as <code>log2(1.2)</code> or <code>log2(1.5)</code> are usually the most useful.</p>
<p>These tests answer a stricter question, so they call fewer genes. With a threshold of 0.5, DESeq2 called 91 genes per experiment and edgeR 123, with realised FDRs of 0.1% and 0.8%. (A call counts as false when the gene did not change at all; no gene in this simulation has a true change between zero and the threshold.)</p>
<p>A fold-change cut applied after the correction, as in the common <code>padj &lt; 0.05</code> plus a minimum fold change, is a different thing. It only removes genes from a list whose FDR is already controlled. In the edgeR runs, cutting the called genes at an absolute log2 fold change of 0.5 removed none of them, since every called gene already had a larger observed change, with a realised FDR of 4.7%, and a cut at 1 left 148 genes with 2.6%. It did not raise the FDR here, but it is not a test of the size of the change either: nothing guarantees that a gene which passes has a true change above the cut-off. When the size matters, use <code>lfcThreshold</code> or <code>glmTreat()</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2: automatic independent filtering, tuned to the cut-off you will use</span></span>
<span id="cb9-2">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb9-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(res)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filterThreshold            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the mean-count cut-off it chose</span></span>
<span id="cb9-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(res)</span>
<span id="cb9-5"></span>
<span id="cb9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2: only changes larger than about 1.4-fold, tested rather than filtered</span></span>
<span id="cb9-7">res_big <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfcThreshold =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb9-8"></span>
<span id="cb9-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR: filter on expression before fitting</span></span>
<span id="cb9-10">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb9-11">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb9-12">fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">robust =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb9-13">qlf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># any change</span></span>
<span id="cb9-14">tr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmTreat</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># changes above a threshold</span></span>
<span id="cb9-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">topTags</span>(tr)</span></code></pre></div></div>
</div>
<p>All the analyses side by side, averaged over the 16 experiments:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_none =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, no filter"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_auto =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, automatic filter"</span>,</span>
<span id="cb10-2">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_fc =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, fold-change pre-filter"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, filterByExpr"</span>,</span>
<span id="cb10-3">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger_fc =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, filterByExpr + fold-change pre-filter"</span>,</span>
<span id="cb10-4">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">deseq_treat =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, lfcThreshold test"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edger_treat =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, glmTreat"</span>)</span>
<span id="cb10-5">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb10-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">analysis =</span> lab[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(tab)],</span>
<span id="cb10-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">genes called</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">num</span>(tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_call"</span>]),</span>
<span id="cb10-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">realised FDR</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>]),</span>
<span id="cb10-9">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">changed genes found</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>]),</span>
<span id="cb10-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">check.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lrrr"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 49%">
<col style="width: 14%">
<col style="width: 14%">
<col style="width: 21%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">analysis</th>
<th style="text-align: right;">genes called</th>
<th style="text-align: right;">realised FDR</th>
<th style="text-align: right;">changed genes found</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">DESeq2, no filter</td>
<td style="text-align: right;">163</td>
<td style="text-align: right;">3.5%</td>
<td style="text-align: right;">34.9%</td>
</tr>
<tr class="even">
<td style="text-align: left;">DESeq2, automatic filter</td>
<td style="text-align: right;">172</td>
<td style="text-align: right;">4.7%</td>
<td style="text-align: right;">36.5%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">DESeq2, fold-change pre-filter</td>
<td style="text-align: right;">191</td>
<td style="text-align: right;">7.1%</td>
<td style="text-align: right;">39.5%</td>
</tr>
<tr class="even">
<td style="text-align: left;">edgeR, filterByExpr</td>
<td style="text-align: right;">167</td>
<td style="text-align: right;">4.7%</td>
<td style="text-align: right;">35.5%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">edgeR, filterByExpr + fold-change pre-filter</td>
<td style="text-align: right;">223</td>
<td style="text-align: right;">16.4%</td>
<td style="text-align: right;">41.4%</td>
</tr>
<tr class="even">
<td style="text-align: left;">DESeq2, lfcThreshold test</td>
<td style="text-align: right;">91</td>
<td style="text-align: right;">0.1%</td>
<td style="text-align: right;">20.3%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">edgeR, glmTreat</td>
<td style="text-align: right;">123</td>
<td style="text-align: right;">0.8%</td>
<td style="text-align: right;">27.2%</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Benjamini Y, Hochberg Y 1995 Journal of the Royal Statistical Society Series B 57(1):289-300 (<a href="https://doi.org/10.1111/j.2517-6161.1995.tb02031.x">doi:10.1111/j.2517-6161.1995.tb02031.x</a>)</li>
<li>Bourgon R, Gentleman R, Huber W 2010 Proceedings of the National Academy of Sciences 107(21):9546-9551 (<a href="https://doi.org/10.1073/pnas.0914005107">doi:10.1073/pnas.0914005107</a>)</li>
<li>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</li>
<li>Chen Y, Lun ATL, Smyth GK 2016 F1000Research 5:1438 (<a href="https://doi.org/10.12688/f1000research.8987.2">doi:10.12688/f1000research.8987.2</a>)</li>
<li>McCarthy DJ, Smyth GK 2009 Bioinformatics 25(6):765-771 (<a href="https://doi.org/10.1093/bioinformatics/btp053">doi:10.1093/bioinformatics/btp053</a>)</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, edgeR 4.8.2,
generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0,
limma 3.66.0, MatrixGenerics 1.22.0, matrixStats 1.5.0, S4Vectors
0.48.1, Seqinfo 1.0.0, SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>DESeq2</category>
  <category>edgeR</category>
  <category>FDR</category>
  <category>RNA-seq</category>
  <category>multiple testing</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/independent-filtering-fdr/</guid>
  <pubDate>Thu, 10 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/independent-filtering-fdr/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>How to read a p-value histogram in RNA-seq</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/p-value-histogram-diagnostics/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-4">})</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.36"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4.0"</span>)</span>
<span id="cb1-6"></span>
<span id="cb1-7">pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f%%"</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-8">num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trim =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-9">dec <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>), x)</span>
<span id="cb1-10"></span>
<span id="cb1-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># negative binomial counts; phi is the dispersion (variance = mu + phi * mu^2)</span></span>
<span id="cb1-12">rnb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(mu, phi) {</span>
<span id="cb1-13">  x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(mu), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi)</span>
<span id="cb1-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(mu))</span>
<span id="cb1-15">}</span>
<span id="cb1-16"></span>
<span id="cb1-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the DESeq2 standard workflow; returns the results table of the last coefficient</span></span>
<span id="cb1-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (alpha = 0.05 because genes are called at 5% FDR; the vignette asks for this when the cutoff is not 0.1)</span></span>
<span id="cb1-19">run_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, coldata, design) {</span>
<span id="cb1-20">  dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(counts, coldata, design)</span>
<span id="cb1-21">  dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tail</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resultsNames</span>(dds), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb1-23">}</span>
<span id="cb1-24"></span>
<span id="cb1-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Storey's estimate of the null fraction with a single lambda</span></span>
<span id="cb1-26">pi0_hat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lambda =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> lambda) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lambda)</span>
<span id="cb1-27"></span>
<span id="cb1-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what we can measure because the truth is known</span></span>
<span id="cb1-29">score <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, is_de) {</span>
<span id="cb1-30">  ok <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(p)</span>
<span id="cb1-31">  p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> p[ok]; is_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> is_de[ok]</span>
<span id="cb1-32">  padj <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(p, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>)</span>
<span id="cb1-33">  call <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb1-34">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">null_p05 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pi0_true =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de),</span>
<span id="cb1-35">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pi0_hat =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pi0_hat</span>(p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_call =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(call),</span>
<span id="cb1-36">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(call)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de[call]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb1-37">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">power =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(is_de)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(call[is_de]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA_real_</span>)</span>
<span id="cb1-38">}</span>
<span id="cb1-39"></span>
<span id="cb1-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># histogram on the density scale, stacked by truth, dashed line at the true null fraction</span></span>
<span id="cb1-41">phist <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(d) {</span>
<span id="cb1-42">  d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">include.lowest =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-43">  d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>truth <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"truly changed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null (no change)"</span>),</span>
<span id="cb1-44">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"truly changed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null (no change)"</span>))</span>
<span id="cb1-45">  tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bin =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">truth =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>truth))</span>
<span id="cb1-46">  tot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel, length)</span>
<span id="cb1-47">  tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>density <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Freq <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(tot[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel)]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb1-48">  tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb1-49">  line <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(tot), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel)),</span>
<span id="cb1-50">                     <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pi0 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de, d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel, mean)))</span>
<span id="cb1-51">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(tab, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(x, density, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> truth)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-52">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-53">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> line, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> pi0), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>,</span>
<span id="cb1-54">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-55">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"truly changed"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null (no change)"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b9b7c6"</span>),</span>
<span id="cb1-56">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-57">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>panel) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-58">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"density"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-59">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-60">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb1-61">          <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>),</span>
<span id="cb1-62">          <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">strip.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>))</span>
<span id="cb1-63">}</span></code></pre></div></div>
</details>
</div>
<p>You have run a differential expression analysis, drawn a histogram of the raw p-values, and it looks odd. Is that a problem? Usually yes, and the shape tells you which kind. A healthy histogram has a flat floor with a spike at zero. A floor that leans towards zero means the test is producing false positives: in the worst example below, 24.3% of genes with no change had p &lt; 0.05, and 55.1% of the genes called at a 5% false discovery rate were false. A floor that leans towards one usually means the test is throwing power away, or that the histogram includes many genes with too few reads to test.</p>
<p>This post simulates RNA-seq counts where the truth is known, runs DESeq2 in four situations, and shows the histogram each one produces, what causes it, and how to fix it.</p>
<section id="why-the-histogram-has-a-floor" class="level2">
<h2 class="anchored" data-anchor-id="why-the-histogram-has-a-floor">Why the histogram has a floor</h2>
<p>A p-value is built so that, for a gene with no real change, every value between 0 and 1 is equally likely, as long as the model fits and the gene has enough reads. Test a few thousand unchanged genes and their p-values fill a histogram evenly: a flat floor. Genes that did change tend to give small p-values and stack up in the first bin. So a good histogram is a mixture of two parts, and the height of the floor tells you roughly what share of genes is null (unchanged).</p>
<p>That last point is the basis of Storey’s estimate of the null fraction, usually written <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>π</mi><mn>0</mn></msub><annotation encoding="application/x-tex">\pi_0</annotation></semantics></math> (Storey and Tibshirani 2003). Take the share of p-values above 0.5 and divide by 0.5: if the right half of the histogram is made only of null genes, this recovers the share of null genes. The estimate is also a handy number for checking a histogram, because a true proportion cannot exceed 1. Breheny, Stromberg and Lambert (2018) give a longer treatment of both uses, inference and diagnosis.</p>
</section>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>Each simulated data set has 3,000 genes and 4 samples per condition, with counts drawn from a negative binomial distribution (the standard model for RNA-seq counts, where the variance grows faster than the mean). Mean expression varies over a realistic range, and the dispersion (the extra, biological part of the variance) is larger for weakly expressed genes. The first 10% of genes are truly changed, by a factor of two up or down; the rest are null.</p>
<p>Every analysis is the DESeq2 standard workflow, <code>DESeq()</code> then <code>results()</code> (Love, Huber and Anders 2014). The only thing that changes between scenarios is how the data were generated and which design formula is used. To score each run I apply the Benjamini-Hochberg adjustment to the raw p-values shown in the histogram and call genes at 5% FDR; because the truth is known, the share of false calls can be counted directly. The full simulation code is in the chunks below.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">n_per <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>                                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># samples per condition</span></span>
<span id="cb2-2">n_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3000</span></span>
<span id="cb2-3">de_frac <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.10</span></span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb2-5">mu0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.2</span>))    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline mean count per gene</span></span>
<span id="cb2-6">phi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> mu0                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># dispersion falls with expression</span></span>
<span id="cb2-7">is_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> de_frac <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_genes</span>
<span id="cb2-8">lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(is_de, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), n_genes, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># +-1 log2 = 2-fold</span></span>
<span id="cb2-9">condition <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n_per))</span>
<span id="cb2-10">size_factor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))</span>
<span id="cb2-11">mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(mu0, size_factor) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(lfc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(condition <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"treat"</span>))</span>
<span id="cb2-12">counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnb</span>(mu, phi)</span>
<span id="cb2-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gene"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes))</span>
<span id="cb2-14">coldata <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">condition =</span> condition)</span>
<span id="cb2-15"></span>
<span id="cb2-16">res_good <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq</span>(counts, coldata, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> condition)</span>
<span id="cb2-17">s_good <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_good<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, is_de)</span></code></pre></div></div>
</div>
</section>
<section id="the-healthy-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-healthy-shape">The healthy shape</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">phist</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res_good<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de,</span>
<span id="cb3-2">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Well-behaved analysis"</span>)))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-good" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Histogram of p-values in 20 bins. The first bin is tall and mostly violet (truly changed genes); every other bin is grey (null genes) and sits close to a dashed horizontal line at the true null fraction.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-good-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/p-value-histogram-diagnostics/index_files/figure-html/fig-good-1.png" class="img-fluid figure-img" alt="Histogram of p-values in 20 bins. The first bin is tall and mostly violet (truly changed genes); every other bin is grey (null genes) and sits close to a dashed horizontal line at the true null fraction." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-good-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: A healthy p-value histogram from DESeq2 on simulated data: a flat floor made of null genes and a spike at zero made of truly changed genes. The dashed line is the true fraction of null genes.
</figcaption>
</figure>
</div>
</div>
</div>
<p>This is what you are hoping to see. The grey floor sits on the dashed line, and 5.2% of the null genes fall below 0.05, which is close to what a p-value promises. Storey’s estimate of the null fraction is 0.88 against a true value of 0.90. At 5% FDR the analysis calls 275 genes, finds 84.0% of the truly changed ones, and 8.4% of its calls are false. That last number is above the 5% target, for two reasons. Part of it is chance: the Benjamini-Hochberg procedure bounds the false discovery rate as an average over repeated experiments, not in every one. Part is that DESeq2’s Wald test is slightly liberal with 4 samples per group, as the 5.2% of nulls below 0.05 hints; repeated runs of this simulation put the false share a little above 5% on average. That excess is small next to Shape 1.</p>
</section>
<section id="shape-1-the-floor-leans-towards-zero" class="level2">
<h2 class="anchored" data-anchor-id="shape-1-the-floor-leans-towards-zero">Shape 1: the floor leans towards zero</h2>
<p>The most dangerous shape is a floor that is higher on the left than on the right. It means null genes are getting small p-values too often: the test is anti-conservative, and the false discovery rate you report is not the one you have.</p>
<p>A common way to get there is to give the model a variance that is too small. Here each of the 8 biological samples was made into one library and sequenced on 3 lanes, and the lanes were then entered as 24 separate samples. Lanes of the same library differ only by sampling noise, so the model sees far less variation between “replicates” than there really is between animals or patients.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">lanes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2027</span>)</span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one library per biological sample (its true expression), then 3 sequencing runs of it</span></span>
<span id="cb4-4">lambda <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rgamma</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(mu), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scale =</span> mu <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> phi), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_genes)</span>
<span id="cb4-5">counts_tech <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(cbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(j)</span>
<span id="cb4-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(lanes), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(l) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rpois</span>(n_genes, lambda[, j] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> lanes))))</span>
<span id="cb4-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts_tech) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts)</span>
<span id="cb4-8">coldata_tech <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">condition =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(condition, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> lanes),</span>
<span id="cb4-9">                           <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sample =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> lanes)))</span>
<span id="cb4-10"></span>
<span id="cb4-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the mistake: every sequencing run treated as a separate sample</span></span>
<span id="cb4-12">res_tech <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq</span>(counts_tech, coldata_tech, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> condition)</span>
<span id="cb4-13">s_tech <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_tech<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, is_de)</span>
<span id="cb4-14"></span>
<span id="cb4-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the fix: sum the runs of each library, then test 4 vs 4</span></span>
<span id="cb4-16">dds_tech <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(counts_tech, coldata_tech, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> condition)</span>
<span id="cb4-17">dds_coll <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collapseReplicates</span>(dds_tech, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">groupby =</span> dds_tech<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sample)</span>
<span id="cb4-18">res_coll <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds_coll, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb4-19">s_coll <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_coll<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, is_de)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">lv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Runs as samples (24 columns)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Runs summed per library (8 columns)"</span>)</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">phist</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb5-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res_tech<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], lv)),</span>
<span id="cb5-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res_coll<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], lv))))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-tech" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two histograms of p-values. Left: a very tall first bin with a large grey (null) share and a floor that slopes down from left to right, ending below the dashed line. Right: a flat grey floor at the dashed line and a violet spike at zero.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-tech-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/p-value-histogram-diagnostics/index_files/figure-html/fig-tech-1.png" class="img-fluid figure-img" alt="Two histograms of p-values. Left: a very tall first bin with a large grey (null) share and a floor that slopes down from left to right, ending below the dashed line. Right: a flat grey floor at the dashed line and a violet spike at zero." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-tech-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Technical replicates treated as biological replicates (left) against the same runs summed per library (right). The left panel is the anti-conservative shape: grey null genes pile up on the left and the floor on the right sinks below the dashed line. The dashed line is the true null fraction in each panel.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With the lanes as samples, 24.3% of null genes have p &lt; 0.05 instead of about 5%. The analysis calls 643 genes at 5% FDR and 55.1% of them are false. Note the tell-tale detail on the right of the histogram: because too many null p-values have moved left, the floor near 1 drops below the dashed line, and Storey’s estimate falls to 0.56 against a true 0.90. The analysis also finds 96.3% of the truly changed genes, but that extra sensitivity is bought with the false calls. A null fraction estimate that is much lower than you would believe for your experiment is a warning in itself.</p>
<p>The fix is to give the model one column per biological unit. DESeq2 has a function for this case, <code>collapseReplicates()</code>, which sums the counts of columns that share a level of <code>groupby</code>; its help page defines technical replicates as multiple sequencing runs of the same library, and the vignette says not to use it on biological replicates. After collapsing, 5.5% of null genes fall below 0.05 and 7.9% of the calls are false.</p>
<p>Treating single cells as replicates in single-cell data is the same mistake as the lanes above, only larger (see <a href="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/">pseudobulk versus cell-level tests</a>). An unmodelled batch that is partly aligned with the condition gives the same lean for a different reason: part of the batch effect is attributed to the condition, so null genes look changed (see <a href="https://pseudocount.com/posts/confounded-batch-and-condition/">the post on confounded batches</a>).</p>
</section>
<section id="shape-2-the-floor-leans-towards-one-low-counts" class="level2">
<h2 class="anchored" data-anchor-id="shape-2-the-floor-leans-towards-one-low-counts">Shape 2: the floor leans towards one (low counts)</h2>
<p>The opposite lean, more mass near 1 than near 0.5, means the test is conservative: null genes get p-values that are too large. That costs power rather than creating false positives, but it also breaks the histogram as a diagnostic, because the floor no longer tells you the null fraction.</p>
<p>A common cause in RNA-seq is harmless. Genes with a handful of reads carry almost no information about a change, and a test on them rarely produces a small p-value. To show it, I add 1,500 null genes with about one read per sample to the healthy data set and rerun the same analysis.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">n_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1500</span></span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2028</span>)</span>
<span id="cb6-3">mu_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_low, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># genes with about one read per sample</span></span>
<span id="cb6-4">counts_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(counts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(mu_low, size_factor), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> mu_low))</span>
<span id="cb6-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts_low) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gene"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(counts_low)))</span>
<span id="cb6-6">is_de_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(is_de, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, n_low))      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the added genes are all null</span></span>
<span id="cb6-7"></span>
<span id="cb6-8">res_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq</span>(counts_low, coldata, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> condition)</span>
<span id="cb6-9">s_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, is_de_low)</span>
<span id="cb6-10">n_low_na <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue))</span>
<span id="cb6-11">n_low_allzero <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(counts_low) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb6-12">n_padj_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2's own adjusted p-values</span></span>
<span id="cb6-13"></span>
<span id="cb6-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the DESeq2 vignette's pre-filter: a count of at least 10 in at least (smallest group size) samples</span></span>
<span id="cb6-15">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(counts_low <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> n_per</span>
<span id="cb6-16">s_kept <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[keep], is_de_low[keep])</span>
<span id="cb6-17">s_dropped <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>keep], is_de_low[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>keep])</span>
<span id="cb6-18">n_dropped <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>keep)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">lv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genes that fail the pre-filter"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genes that pass the pre-filter"</span>)</span>
<span id="cb7-2">ok <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue)</span>
<span id="cb7-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">phist</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res_low<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[ok], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de_low[ok],</span>
<span id="cb7-4">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(keep[ok], lv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], lv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), lv)))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-low" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two histograms of p-values. Left, genes that fail the count filter: almost all grey, with a short first bin and bars that rise towards 1. Right, genes that pass: a flat grey floor at the dashed line and a violet spike at zero.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-low-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/p-value-histogram-diagnostics/index_files/figure-html/fig-low-1.png" class="img-fluid figure-img" alt="Two histograms of p-values. Left, genes that fail the count filter: almost all grey, with a short first bin and bars that rise towards 1. Right, genes that pass: a flat grey floor at the dashed line and a violet spike at zero." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-low-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: The same DESeq2 run, split by the DESeq2 vignette’s pre-filter. The genes that fail it (left) produce p-values that pile up towards 1; the genes that pass it (right) give the healthy shape. The dashed line is the true null fraction in each panel.
</figcaption>
</figure>
</div>
</div>
</div>
<p>Across all genes, Storey’s estimate of the null fraction is now 1.04, an impossible value, against a true 0.93. The excess comes from a subset of genes, and splitting the histogram shows which. The DESeq2 vignette suggests keeping genes with a count of at least 10 in at least as many samples as the smallest group. Of the 1,509 genes that fail this filter, 65 have zero counts in every sample; DESeq2 leaves their p-value empty (missing), and the other 1,444 give the left panel: only 1.0% of their null p-values fall below 0.05, and their bars climb towards 1. The genes that pass give the healthy shape on the right, with 4.9% of nulls below 0.05 and a null fraction estimate of 0.89 (true value 0.90).</p>
<p>This shape needs a filter, not a new model. Filtering on a statistic computed without the condition labels, such as the overall mean count, is legitimate as long as the filter is (close to) independent of the test p-value for null genes (Bourgon, Gentleman and Huber 2010). DESeq2 already does this for its adjusted p-values: <code>results()</code> applies independent filtering on the mean of normalised counts by default and leaves <code>padj</code> missing for genes below the chosen threshold, and in this run its own <code>padj</code> column gives 268 genes at 5% FDR. What it does not do is filter the <code>pvalue</code> column, so a histogram of <code>res$pvalue</code> shows the tilt. Plot the genes that pass the filter.</p>
</section>
<section id="shape-3-a-u-spike-at-zero-and-a-ramp-towards-one" class="level2">
<h2 class="anchored" data-anchor-id="shape-3-a-u-spike-at-zero-and-a-ramp-towards-one">Shape 3: a U, spike at zero and a ramp towards one</h2>
<p>The third shape has a spike at zero, a dip, and then a floor that climbs towards 1. The ramp says null genes are getting p-values that are too large; the spike says some real signal is still getting through. If the ramp stays after you remove low-count genes, the problem is the model.</p>
<p>Here the data come from a paired design: 4 donors each give one control and one treated sample, and every gene has its own donor-to-donor differences. The common slip is to leave the donor out of the design formula.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">donor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_per), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">times =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># each donor gives one ctrl and one treated sample</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2029</span>)</span>
<span id="cb8-3">donor_effect <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_per, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_genes)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log2 scale</span></span>
<span id="cb8-4">counts_pair <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnb</span>(mu <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>donor_effect[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(donor)], phi)</span>
<span id="cb8-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts_pair) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(counts)</span>
<span id="cb8-6">coldata_pair <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">condition =</span> condition, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor =</span> donor)</span>
<span id="cb8-7"></span>
<span id="cb8-8">res_unpaired <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq</span>(counts_pair, coldata_pair, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> condition)</span>
<span id="cb8-9">res_paired <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq</span>(counts_pair, coldata_pair, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> donor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> condition)</span>
<span id="cb8-10">s_unpaired <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_unpaired<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, is_de)</span>
<span id="cb8-11">s_paired <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_paired<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, is_de)</span>
<span id="cb8-12"></span>
<span id="cb8-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># is it the counts or the model? apply the same pre-filter</span></span>
<span id="cb8-14">keep_pair <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(counts_pair <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> n_per</span>
<span id="cb8-15">s_unpaired_kept <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(res_unpaired<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[keep_pair], is_de[keep_pair])</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">lv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ condition (donor ignored)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ donor + condition"</span>)</span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">phist</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res_unpaired<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], lv)),</span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res_paired<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], lv))))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-paired" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two histograms of p-values. Left: a moderate first bin, low bars from 0.05 to about 0.3, then grey bars rising towards 1 and ending above the dashed line, forming a U. Right: a flat grey floor at the dashed line and a tall violet spike at zero.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-paired-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/p-value-histogram-diagnostics/index_files/figure-html/fig-paired-1.png" class="img-fluid figure-img" alt="Two histograms of p-values. Left: a moderate first bin, low bars from 0.05 to about 0.3, then grey bars rising towards 1 and ending above the dashed line, forming a U. Right: a flat grey floor at the dashed line and a tall violet spike at zero." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-paired-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;4: A paired design analysed without the donor term (left) and with it (right). Leaving the donor out gives the U shape: a spike at zero from the strongest changed genes and a ramp of null genes towards 1. The dashed line is the true null fraction in each panel.
</figcaption>
</figure>
</div>
</div>
</div>
<p>Without the donor term, the differences between donors have nowhere to go but into the noise estimate, and the test becomes conservative: 0.6% of null genes fall below 0.05 and the null fraction estimate is 1.26. The price is power. At 5% FDR the analysis calls 8 genes and finds 2.7% of the truly changed ones. Restricting to the 2,968 genes that pass the count filter does not help (null fraction estimate 1.26), which is how you know this is not the low count shape.</p>
<p>With <code>~ donor + condition</code>, each gene is compared within donors, and the histogram returns to the healthy shape: 4.9% of nulls below 0.05, 239 calls, 75.3% of changed genes found and 5.4% of calls false.</p>
</section>
<section id="all-seven-analyses-side-by-side" class="level2">
<h2 class="anchored" data-anchor-id="all-seven-analyses-side-by-side">All seven analyses side by side</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">rows <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Well-behaved"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_good,</span>
<span id="cb10-2">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Runs as samples"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_tech, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Runs summed"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_coll,</span>
<span id="cb10-3">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Low counts, all genes"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_low, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Low counts, pre-filtered"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_kept,</span>
<span id="cb10-4">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Paired, donor ignored"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_unpaired, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Paired, donor in model"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> s_paired)</span>
<span id="cb10-5">tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb10-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">analysis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(rows),</span>
<span id="cb10-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nulls with p &lt; 0.05</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(rows, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>null_p05)),</span>
<span id="cb10-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pi0 estimate (truth)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(rows, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dec</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pi0_hat), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" ("</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dec</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pi0_true), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">")"</span>)),</span>
<span id="cb10-9">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">calls at 5% FDR</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(rows, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">num</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>n_call)),</span>
<span id="cb10-10">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false among calls</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(rows, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp)),</span>
<span id="cb10-11">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">changed genes found</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(rows, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power)),</span>
<span id="cb10-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">check.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>)</span>
<span id="cb10-13">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(tab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lrrrrr"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 20%">
<col style="width: 16%">
<col style="width: 17%">
<col style="width: 13%">
<col style="width: 15%">
<col style="width: 16%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">analysis</th>
<th style="text-align: right;">nulls with p &lt; 0.05</th>
<th style="text-align: right;">pi0 estimate (truth)</th>
<th style="text-align: right;">calls at 5% FDR</th>
<th style="text-align: right;">false among calls</th>
<th style="text-align: right;">changed genes found</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Well-behaved</td>
<td style="text-align: right;">5.2%</td>
<td style="text-align: right;">0.88 (0.90)</td>
<td style="text-align: right;">275</td>
<td style="text-align: right;">8.4%</td>
<td style="text-align: right;">84.0%</td>
</tr>
<tr class="even">
<td style="text-align: left;">Runs as samples</td>
<td style="text-align: right;">24.3%</td>
<td style="text-align: right;">0.56 (0.90)</td>
<td style="text-align: right;">643</td>
<td style="text-align: right;">55.1%</td>
<td style="text-align: right;">96.3%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Runs summed</td>
<td style="text-align: right;">5.5%</td>
<td style="text-align: right;">0.88 (0.90)</td>
<td style="text-align: right;">265</td>
<td style="text-align: right;">7.9%</td>
<td style="text-align: right;">81.3%</td>
</tr>
<tr class="even">
<td style="text-align: left;">Low counts, all genes</td>
<td style="text-align: right;">3.6%</td>
<td style="text-align: right;">1.04 (0.93)</td>
<td style="text-align: right;">256</td>
<td style="text-align: right;">6.6%</td>
<td style="text-align: right;">79.7%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Low counts, pre-filtered</td>
<td style="text-align: right;">4.9%</td>
<td style="text-align: right;">0.89 (0.90)</td>
<td style="text-align: right;">271</td>
<td style="text-align: right;">8.1%</td>
<td style="text-align: right;">83.6%</td>
</tr>
<tr class="even">
<td style="text-align: left;">Paired, donor ignored</td>
<td style="text-align: right;">0.6%</td>
<td style="text-align: right;">1.26 (0.90)</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;">0.0%</td>
<td style="text-align: right;">2.7%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Paired, donor in model</td>
<td style="text-align: right;">4.9%</td>
<td style="text-align: right;">0.93 (0.90)</td>
<td style="text-align: right;">239</td>
<td style="text-align: right;">5.4%</td>
<td style="text-align: right;">75.3%</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>Make the histogram every time, before you look at the gene list, and split it by expression so that the low-count tilt cannot hide a real problem or pass for one. With DESeq2 the split can reuse the threshold that independent filtering chose, which is how the DESeq2 vignette draws its own p-value histogram:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> res_low                                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># your results() table</span></span>
<span id="cb11-2">use <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>baseMean <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span>(res)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>filterThreshold</span>
<span id="cb11-3">pi0_split <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pass =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pi0_hat</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[use])),</span>
<span id="cb11-4">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fail =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pi0_hat</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>use])))</span>
<span id="cb11-5">pi0_split</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>     pass      fail 
0.9033694 1.3716059 </code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hist</span>(res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[use], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">main =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genes passing the filter"</span>)</span>
<span id="cb13-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hist</span>(res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>use], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">main =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genes filtered out"</span>)</span></code></pre></div></div>
</div>
<p>On the low-count data set from above, the null fraction estimate is 0.90 for the genes that pass this threshold and 1.37 for those that fail it.</p>
<p>Then read the part of the histogram that passes the filter. A flat floor with a spike is fine. A floor leaning towards zero, or a null fraction estimate far below what you believe, points to replicates that are not independent (sequencing runs or cells entered as samples) or to a batch partly aligned with the condition. A floor leaning towards one that survives the filter points to a donor or batch, balanced across conditions, that is in the experiment but missing from the formula.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Storey JD, Tibshirani R 2003 Proceedings of the National Academy of Sciences 100(16):9440-9445 (<a href="https://doi.org/10.1073/pnas.1530509100">doi:10.1073/pnas.1530509100</a>)</li>
<li>Breheny PJ, Stromberg AJ, Lambert J 2018 High-Throughput 7(3):23 (<a href="https://doi.org/10.3390/ht7030023">doi:10.3390/ht7030023</a>)</li>
<li>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</li>
<li>Bourgon R, Gentleman R, Huber W 2010 Proceedings of the National Academy of Sciences 107(21):9546-9551 (<a href="https://doi.org/10.1073/pnas.0914005107">doi:10.1073/pnas.0914005107</a>)</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, generics 0.1.4,
GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0, MatrixGenerics
1.22.0, matrixStats 1.5.0, S4Vectors 0.48.1, Seqinfo 1.0.0,
SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>DESeq2</category>
  <category>RNA-seq</category>
  <category>FDR</category>
  <category>diagnostics</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/p-value-histogram-diagnostics/</guid>
  <pubDate>Mon, 07 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/p-value-histogram-diagnostics/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>CPM vs TMM: composition bias in RNA-seq counts</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/library-size-vs-composition/</link>
  <description><![CDATA[ 





<p>You have a table of RNA-seq counts. You divide each sample by its total number of reads, multiply by a million, and compare conditions. That is counts per million (CPM), the first normalisation most people meet, and the question that follows is usually some version of “CPM or TMM, and does it matter?”</p>
<p>It matters when a few genes take a larger share of the reads in one condition. CPM corrects for how deeply each sample was sequenced, but not for what the reads were spent on. If a handful of highly expressed genes go up, every other gene gets a smaller slice of the same library, and CPM reports that smaller slice as down-regulation. In the simulation below, 20 of 4,000 genes go up 10-fold. Under plain CPM the typical unchanged gene shows a log2 fold change of -0.55, and an edgeR test on raw library sizes calls 1,457 of 3,972 tested unchanged genes significant at 5% FDR. With TMM normalisation the median shift is -0.001 and the false calls drop to 0.</p>
<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-5">})</span>
<span id="cb1-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># glmQLFit(legacy = FALSE) needs 4.0.0</span></span>
<span id="cb1-7">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.40"</span>,</span>
<span id="cb1-8">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4.0"</span>)</span>
<span id="cb1-9"></span>
<span id="cb1-10">fmt  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formatC</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> d)</span>
<span id="cb1-11">fmtn <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formatC</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>)</span>
<span id="cb1-12">pct  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formatC</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">format =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> d)</span>
<span id="cb1-13">violet <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>; magenta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>; grey <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8797"</span>; grey_dark <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#3d3b4a"</span></span>
<span id="cb1-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_set</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb1-16">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>)))</span></code></pre></div></div>
</details>
</div>
<section id="why-dividing-by-the-total-goes-wrong" class="level2">
<h2 class="anchored" data-anchor-id="why-dividing-by-the-total-goes-wrong">Why dividing by the total goes wrong</h2>
<p>Sequencing does not count molecules; it samples a fixed number of reads from the pool of cDNA. What you observe for each gene is its share of that pool. If the up genes held a fraction <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>s</mi><annotation encoding="application/x-tex">s</annotation></semantics></math> of the reads in condition A and rise <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>f</mi><annotation encoding="application/x-tex">f</annotation></semantics></math>-fold in condition B, the reads left for everything else fall from <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>−</mo><mi>s</mi></mrow><annotation encoding="application/x-tex">1 - s</annotation></semantics></math> to <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false" form="prefix">(</mo><mn>1</mn><mo>−</mo><mi>s</mi><mo stretchy="false" form="postfix">)</mo><mi>/</mi><mo stretchy="false" form="prefix">(</mo><mn>1</mn><mo>−</mo><mi>s</mi><mo>+</mo><mi>s</mi><mi>f</mi><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">(1 - s) / (1 - s + s f)</annotation></semantics></math> of the library. A gene whose absolute expression did not change therefore shows, after dividing by the total, a log2 fold change of</p>
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>−</mi><msub><mrow><mi mathvariant="normal">log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mo stretchy="false" form="prefix">(</mo><mn>1</mn><mo>−</mo><mi>s</mi><mo>+</mo><mi>s</mi><mi>f</mi><mo stretchy="false" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">
-\log_2 (1 - s + s f)
</annotation></semantics></math></p>
<p>Nothing about the replicates or the test enters this expression. The shift is a property of the normalisation, and more replicates only make it more significant.</p>
</section>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>The simulation has 4,000 genes and 3 samples per condition. Counts are negative binomial with dispersion 0.05, which is a biological coefficient of variation of about 22%, and library sizes are drawn between 8 and 12 million reads. The 20 genes that change together take 5% of the reads in condition A; in condition B they go up 10-fold and their share rises to 34%. The other 3,980 genes keep exactly the same expression, so their true log2 fold change is zero. The formula above predicts that total-count scaling will put them at -0.54.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">n_per_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># replicates per condition</span></span>
<span id="cb2-2">phi         <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># negative binomial dispersion (biological CV about 22%)</span></span>
<span id="cb2-3">lib_range   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8e6</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">12e6</span>)</span>
<span id="cb2-4">n_rep       <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># simulated datasets per setting in the fold-change sweep</span></span>
<span id="cb2-5">n_rep_frac  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># and in the fraction sweep, whose ratios are noisier</span></span>
<span id="cb2-6">fc_frac     <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># fold change used in the last sweep</span></span>
<span id="cb2-7"></span>
<span id="cb2-8">simulate_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">G =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">up =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">share =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>,</span>
<span id="cb2-9">                            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> n_per_group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> phi) {</span>
<span id="cb2-10">  w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rlnorm</span>(G, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">meanlog =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sdlog =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline expression shape</span></span>
<span id="cb2-11">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.null</span>(share)) {                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># fix the up genes' share of reads in A</span></span>
<span id="cb2-12">    w[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>up] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> w[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>up] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(w[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>up]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> share)</span>
<span id="cb2-13">    w[up]  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> share <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(up)</span>
<span id="cb2-14">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb2-15">    w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> w <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(w)</span>
<span id="cb2-16">  }</span>
<span id="cb2-17">  pA <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> w</span>
<span id="cb2-18">  pB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> w; pB[up] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pB[up] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> fc; pB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pB <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(pB) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same molecules, new proportions</span></span>
<span id="cb2-19">  lib <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n, lib_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], lib_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sequencing depth</span></span>
<span id="cb2-20">  mu  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sweep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(pA, G, n), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(pB, G, n)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, lib, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*"</span>)</span>
<span id="cb2-21">  y   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(mu), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> disp), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> G)</span>
<span id="cb2-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">storage.mode</span>(y) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"integer"</span></span>
<span id="cb2-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dimnames</span>(y) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gene"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(G)),</span>
<span id="cb2-24">                      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n)))</span>
<span id="cb2-25">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n)),</span>
<span id="cb2-26">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">changed =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(G) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> up,</span>
<span id="cb2-27">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shareB =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(pB[up]),</span>
<span id="cb2-28">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expected =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(pB[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>up]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(pA[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>up])))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what total-count scaling will show</span></span>
<span id="cb2-29">}</span>
<span id="cb2-30"></span>
<span id="cb2-31">share_A <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>; fc_true <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb2-32"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">404</span>)</span>
<span id="cb2-33">sim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">share =</span> share_A, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> fc_true)</span>
<span id="cb2-34">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y; group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group</span>
<span id="cb2-35">n_genes   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(y)</span>
<span id="cb2-36">n_changed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed)</span>
<span id="cb2-37">n_unchanged <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n_changed</span>
<span id="cb2-38">share_B   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>shareB</span>
<span id="cb2-39">expected_offset <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>expected</span>
<span id="cb2-40">expected_ratio  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>expected_offset</span>
<span id="cb2-41">bcv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(phi)</span></code></pre></div></div>
</div>
<p>Two assumptions carry the result. The first is that only a small minority of genes change, which is what TMM and median-of-ratios rely on; the last section breaks it on purpose. The second is that the changed genes are highly expressed, because a gene has to hold a real share of the library to move everyone else: in the formula, a small <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>s</mi><annotation encoding="application/x-tex">s</annotation></semantics></math> keeps the shift small even for a large <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>f</mi><annotation encoding="application/x-tex">f</annotation></semantics></math>.</p>
</section>
<section id="three-ways-to-scale-the-same-counts" class="level2">
<h2 class="anchored" data-anchor-id="three-ways-to-scale-the-same-counts">Three ways to scale the same counts</h2>
<p>Below, each gene’s log2 fold change is computed three ways: dividing by the raw library size (plain CPM), by the TMM effective library size from edgeR, and by the DESeq2 median-of-ratios size factor.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">lib_raw <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(y)</span>
<span id="cb3-2">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb3-3">d_tmm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(d)                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># TMM is the default method</span></span>
<span id="cb3-4">eff_lib <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> lib_raw <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> d_tmm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>norm.factors   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># effective library sizes</span></span>
<span id="cb3-5"></span>
<span id="cb3-6">sf_mor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateSizeFactorsForMatrix</span>(y)         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2 median-of-ratios</span></span>
<span id="cb3-7"></span>
<span id="cb3-8">log2_ratio <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(scale) {</span>
<span id="cb3-9">  z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sweep</span>(y, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, scale, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/"</span>)</span>
<span id="cb3-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(z[, group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(z[, group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>]))</span>
<span id="cb3-11">}</span>
<span id="cb3-12">expressed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(y) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb3-13">unchanged <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> expressed</span>
<span id="cb3-14">ma <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb3-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">A =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sweep</span>(y, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, lib_raw <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e6</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>),</span>
<span id="cb3-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc_cpm =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2_ratio</span>(lib_raw),</span>
<span id="cb3-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc_tmm =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2_ratio</span>(eff_lib),</span>
<span id="cb3-18">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc_mor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2_ratio</span>(sf_mor),</span>
<span id="cb3-19">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">changed =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed)[expressed, ]</span>
<span id="cb3-20"></span>
<span id="cb3-21">med_cpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc_cpm[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed])</span>
<span id="cb3-22">med_tmm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc_tmm[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed])</span>
<span id="cb3-23">med_mor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc_mor[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed])</span>
<span id="cb3-24">n_unch_expr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(unchanged)</span>
<span id="cb3-25">tmm_ratio <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(d_tmm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>norm.factors[group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>]))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span></span>
<span id="cb3-26">             <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(d_tmm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>norm.factors[group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>])))</span>
<span id="cb3-27">cpm_drop <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>med_cpm           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># apparent fractional drop of a typical unchanged gene</span></span></code></pre></div></div>
</div>
<p>TMM, the trimmed mean of M-values (Robinson and Oshlack 2010), compares each sample with a reference sample gene by gene. For every gene it takes the log ratio between the two (the M-value) and the average log expression (the A-value), trims 30% of the M-values from each tail and 5% of the A-values from each tail, and takes a weighted mean of what is left. The 20 up genes have extreme M-values, so they are trimmed away and the factor is set by the genes that did not change. In edgeR the result is stored as a normalisation factor that multiplies the library size into an effective library size.</p>
<p>Median-of-ratios, the method from Anders and Huber (2010) that DESeq2 uses (Love et al.&nbsp;2014), builds a pseudo-reference sample from the geometric mean of each gene across all samples, then takes the median over genes of each sample’s ratio to that reference. Genes with a zero in any sample are left out. A median barely moves when 20 genes out of thousands shift, so the size factor again reflects the unchanged majority.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">ma_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(ma[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"changed"</span>)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc_cpm,</span>
<span id="cb4-3">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Total count (plain CPM)"</span>),</span>
<span id="cb4-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(ma[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"changed"</span>)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> ma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc_tmm,</span>
<span id="cb4-5">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM effective library size"</span>))</span>
<span id="cb4-6">ma_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(ma_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(ma_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling))</span>
<span id="cb4-7">ma_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ma_long[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">order</span>(ma_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed), ]</span>
<span id="cb4-8">offset_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(ma_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb4-9">                                         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(ma_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling)),</span>
<span id="cb4-10">                        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> expected_offset)</span>
<span id="cb4-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(ma_long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(A, lfc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> changed)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> offset_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> y), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>,</span>
<span id="cb4-15">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FALSE</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">TRUE</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta),</span>
<span id="cb4-17">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unchanged"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"made to go up"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>scaling) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.5</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"average log2 CPM"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log2 fold change, B vs A"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-ma" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two scatter plots of log2 fold change against average log2 CPM. In the left panel, scaled by total count, the cloud of unchanged violet genes sits below zero along the dashed line while the magenta up-regulated genes sit high above. In the right panel, scaled by TMM, the violet cloud is centred on zero and the magenta genes are still high.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-ma-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/library-size-vs-composition/index_files/figure-html/fig-ma-1.png" class="img-fluid figure-img" alt="Two scatter plots of log2 fold change against average log2 CPM. In the left panel, scaled by total count, the cloud of unchanged violet genes sits below zero along the dashed line while the magenta up-regulated genes sit high above. In the right panel, scaled by TMM, the violet cloud is centred on zero and the magenta genes are still high." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-ma-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: MA plots of the same simulated counts, scaled by total count (left) and by TMM effective library size (right). Violet: unchanged genes; magenta: the genes that were made to go up. The dashed line is the shift that total-count scaling must produce.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The left panel is what plain CPM does. The violet cloud of unchanged genes does not sit on zero: it sits on the dashed line, with a median log2 fold change of -0.55 against the predicted -0.54. On the original scale a typical unchanged gene looks 32% lower in condition B. In the right panel TMM has put the cloud back on zero: the median is -0.001, and median-of-ratios gives -0.004.</p>
<p>TMM gets there by giving the condition B samples smaller effective library sizes. The ratio of normalisation factors, B over A, is 0.68; the ratio needed to cancel the shift exactly is 0.69. In plain words, TMM has worked out that part of each B library was spent on the 20 up genes, and it stops counting those reads when it scales everything else.</p>
</section>
<section id="what-the-shift-does-to-a-differential-expression-test" class="level2">
<h2 class="anchored" data-anchor-id="what-the-shift-does-to-a-differential-expression-test">What the shift does to a differential expression test</h2>
<p>A shift of half a log2 unit is not a cosmetic problem once a test sees it. Here the same counts go through the edgeR quasi-likelihood pipeline (<code>filterByExpr</code>, <code>estimateDisp</code>, <code>glmQLFit</code>, <code>glmQLFTest</code>, with <code>legacy = FALSE</code> set explicitly so that older and newer edgeR versions fit the same model) and the standard DESeq2 pipeline, each run twice: once with only total-count scaling, once with its own composition-aware normalisation. For edgeR, total-count scaling is <code>normLibSizes(method = "none")</code>, which is what you get if you skip the normalisation step; for DESeq2 it means setting the size factors to the library sizes before calling <code>DESeq()</code>.</p>
<p>Neither package does this by default. The edgeR help page for <code>normLibSizes()</code> makes the same point with a toy example (CPM on raw library sizes makes two samples look different, normalised library sizes make most of their CPMs equal), and the DESeq2 vignette lists size factor estimation (<code>estimateSizeFactors()</code>, median-of-ratios by default) as the first step inside <code>DESeq()</code>. The DESeq2 total-count arm below needed a deliberate override; in real work DESeq2 users meet this bias through hand-set size factors or by starting from CPM or TPM tables.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>group)</span>
<span id="cb5-2"></span>
<span id="cb5-3">run_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(y, group, method) {</span>
<span id="cb5-4">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb5-5">  keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(d)</span>
<span id="cb5-6">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> d[keep, , keep.lib.sizes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>]</span>
<span id="cb5-7">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> method)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># method = "none" gives plain total-count scaling</span></span>
<span id="cb5-8">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateDisp</span>(d, design)</span>
<span id="cb5-9">  fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(d, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the newer QL method, set explicitly</span></span>
<span id="cb5-10">  tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table</span>
<span id="cb5-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gene =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(tab), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>logFC, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue,</span>
<span id="cb5-12">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padj =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(tab<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>))</span>
<span id="cb5-13">}</span>
<span id="cb5-14"></span>
<span id="cb5-15">run_deseq2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(y, group, libsize_only) {</span>
<span id="cb5-16">  dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(y, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>group)</span>
<span id="cb5-17">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (libsize_only) {</span>
<span id="cb5-18">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sizeFactors</span>(dds) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(y) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(y))))</span>
<span id="cb5-19">  }                                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># otherwise DESeq() estimates median-of-ratios</span></span>
<span id="cb5-20">  dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb5-21">  res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb5-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gene =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(res), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange,</span>
<span id="cb5-23">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padj =</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj)</span>
<span id="cb5-24">}</span>
<span id="cb5-25"></span>
<span id="cb5-26">fits <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb5-27">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, total count"</span>          <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_edger</span>(y, group, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>),</span>
<span id="cb5-28">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, TMM"</span>                  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_edger</span>(y, group, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>),</span>
<span id="cb5-29">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, total count"</span>         <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq2</span>(y, group, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb5-30">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, median-of-ratios"</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq2</span>(y, group, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>))</span>
<span id="cb5-31"></span>
<span id="cb5-32">changed_names <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(y)[sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed]</span>
<span id="cb5-33">summ <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(fits), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m) {</span>
<span id="cb5-34">  f <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fits[[m]]; nul <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>(f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>gene <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> changed_names)</span>
<span id="cb5-35">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> m,</span>
<span id="cb5-36">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tested_unchanged =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(nul),</span>
<span id="cb5-37">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">median_lfc =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc[nul], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb5-38">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_below_05 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p[nul] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb5-39">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false_calls =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj[nul] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb5-40">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false_down =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj[nul] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc[nul] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb5-41">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_calls =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(f<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>nul] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>))</span>
<span id="cb5-42">}))</span>
<span id="cb5-43">getm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m, col) summ[summ<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> m, col]</span>
<span id="cb5-44">fp_edger_cpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_calls"</span>)</span>
<span id="cb5-45">fp_edger_tmm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, TMM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_calls"</span>)</span>
<span id="cb5-46">fp_deseq_cpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_calls"</span>)</span>
<span id="cb5-47">fp_deseq_mor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, median-of-ratios"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_calls"</span>)</span>
<span id="cb5-48">down_edger_cpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_down"</span>)</span>
<span id="cb5-49">tested_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tested_unchanged"</span>)</span>
<span id="cb5-50">p05_edger_cpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p_below_05"</span>)</span>
<span id="cb5-51">p05_deseq_cpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p_below_05"</span>)</span>
<span id="cb5-52">p05_edger_tmm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR, TMM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p_below_05"</span>)</span>
<span id="cb5-53">p05_deseq_mor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, median-of-ratios"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p_below_05"</span>)</span>
<span id="cb5-54">min_true_calls <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(summ<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>true_calls)</span>
<span id="cb5-55">down_deseq_mor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, median-of-ratios"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_down"</span>)</span>
<span id="cb5-56">up_deseq_mor   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fp_deseq_mor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> down_deseq_mor</span>
<span id="cb5-57">tested_deseq   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, total count"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tested_unchanged"</span>)</span>
<span id="cb5-58">true_deseq_mor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getm</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2, median-of-ratios"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true_calls"</span>)</span>
<span id="cb5-59">fdp_deseq_mor  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fp_deseq_mor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (fp_deseq_mor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> true_deseq_mor)</span>
<span id="cb5-60">alpha_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>results)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>alpha</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform</span>(summ,</span>
<span id="cb6-2">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tested_unchanged =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmtn</span>(tested_unchanged),</span>
<span id="cb6-3">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">median_lfc =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"^-(0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.0+)$"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">1"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmt</span>(median_lfc, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)),</span>
<span id="cb6-4">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_below_05 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pct</span>(p_below_05), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%"</span>),</span>
<span id="cb6-5">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false_calls =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmtn</span>(false_calls),</span>
<span id="cb6-6">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">false_down =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fmtn</span>(false_down)),</span>
<span id="cb6-7">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col.names =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"analysis"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unchanged genes tested"</span>,</span>
<span id="cb6-8">                           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"median fitted log2FC (unchanged)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unchanged with p &lt; 0.05"</span>,</span>
<span id="cb6-9">                           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false calls (FDR 5%)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"of which down"</span>,</span>
<span id="cb6-10">                           <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true calls (of "</span>, n_changed, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">")"</span>)),</span>
<span id="cb6-11">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lrrrrrr"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<table class="caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 15%">
<col style="width: 14%">
<col style="width: 20%">
<col style="width: 15%">
<col style="width: 13%">
<col style="width: 8%">
<col style="width: 11%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">analysis</th>
<th style="text-align: right;">unchanged genes tested</th>
<th style="text-align: right;">median fitted log2FC (unchanged)</th>
<th style="text-align: right;">unchanged with p &lt; 0.05</th>
<th style="text-align: right;">false calls (FDR 5%)</th>
<th style="text-align: right;">of which down</th>
<th style="text-align: right;">true calls (of 20)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">edgeR, total count</td>
<td style="text-align: right;">3,972</td>
<td style="text-align: right;">-0.554</td>
<td style="text-align: right;">52.1%</td>
<td style="text-align: right;">1,457</td>
<td style="text-align: right;">1,457</td>
<td style="text-align: right;">20</td>
</tr>
<tr class="even">
<td style="text-align: left;">edgeR, TMM</td>
<td style="text-align: right;">3,972</td>
<td style="text-align: right;">0.000</td>
<td style="text-align: right;">4.7%</td>
<td style="text-align: right;">0</td>
<td style="text-align: right;">0</td>
<td style="text-align: right;">20</td>
</tr>
<tr class="odd">
<td style="text-align: left;">DESeq2, total count</td>
<td style="text-align: right;">3,980</td>
<td style="text-align: right;">-0.554</td>
<td style="text-align: right;">52.9%</td>
<td style="text-align: right;">1,526</td>
<td style="text-align: right;">1,526</td>
<td style="text-align: right;">20</td>
</tr>
<tr class="even">
<td style="text-align: left;">DESeq2, median-of-ratios</td>
<td style="text-align: right;">3,980</td>
<td style="text-align: right;">-0.004</td>
<td style="text-align: right;">5.2%</td>
<td style="text-align: right;">5</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">20</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>With total-count scaling, 52% of the unchanged genes have <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>&lt;</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p &lt; 0.05</annotation></semantics></math> in edgeR and 53% in DESeq2, where 5% is what a calibrated test gives. At a false discovery rate of 5%, edgeR calls 1,457 of 3,972 tested unchanged genes and DESeq2 calls 1,526 of 3,980. All 1,457 of the edgeR false calls are down-regulated: this is the shift from the MA plot turned into a gene list.</p>
<p>With the recommended normalisation the pile disappears. edgeR with TMM makes 0 false calls and 4.7% of unchanged genes fall below <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>=</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p = 0.05</annotation></semantics></math>. DESeq2 with median-of-ratios makes 5 (4 up, 1 down), with 5.2% below <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>=</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p = 0.05</annotation></semantics></math>. That is still a false discovery proportion of 20% among its calls, well above the 5% target, but it is a different problem: with only 20 real changes, a handful of false calls is a large proportion, and DESeq2 runs slightly liberal with 3 replicates per group. A control run on data where nothing changes at all shows this directly:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">405</span>)</span>
<span id="cb7-2">sim0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">share =</span> share_A, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the same genes, no change</span></span>
<span id="cb7-3">null_edger  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_edger</span>(sim0<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y, sim0<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>)</span>
<span id="cb7-4">null_deseq2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_deseq2</span>(sim0<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y, sim0<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb7-5">p05_null_edger  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(null_edger<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb7-6">p05_null_deseq2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(null_deseq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
</div>
<p>With no change anywhere there is no composition effect to correct, yet DESeq2 still puts 5.9% of genes below <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>=</mo><mn>0.05</mn></mrow><annotation encoding="application/x-tex">p = 0.05</annotation></semantics></math>, against 5.3% for edgeR. The excess comes from the test with 3 replicates, not from the scaling. Every analysis in the table finds 20 of the 20 genes that really changed, so skipping composition-aware normalisation buys no power. It only adds false positives.</p>
<p>The median column in the table is the fitted log fold change from each test, so it differs a little from the direct ratios of scaled counts in the MA plot; both put the unchanged genes at zero once the scaling accounts for composition.</p>
<p>One DESeq2 detail, since the threshold here is 5%: the <code>alpha</code> argument of <code>results()</code> defaults to 0.1, and that value sets the target for its independent filtering. If you report genes at FDR 5%, pass <code>alpha = 0.05</code> as done above.</p>
</section>
<section id="how-large-the-shift-gets" class="level2">
<h2 class="anchored" data-anchor-id="how-large-the-shift-gets">How large the shift gets</h2>
<p>The size of the bias depends on how much of the library the changing genes capture. The next simulation keeps the 20 genes at 5% of the reads in condition A and varies how far they go up, with 3 simulated datasets per setting.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">offsets <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(s) {</span>
<span id="cb8-2">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y; A <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>; B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>A</span>
<span id="cb8-3">  keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>changed <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(y) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb8-4">  med <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(scale) {</span>
<span id="cb8-5">    z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sweep</span>(y, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, scale, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/"</span>)</span>
<span id="cb8-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(z[keep, B]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(z[keep, A])))</span>
<span id="cb8-7">  }</span>
<span id="cb8-8">  lib <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(y)</span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">total =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">med</span>(lib), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">TMM =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">med</span>(lib <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y)),</span>
<span id="cb8-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">MoR =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">med</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateSizeFactorsForMatrix</span>(y)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expected =</span> s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>expected)</span>
<span id="cb8-11">}</span>
<span id="cb8-12"></span>
<span id="cb8-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb8-14">fold_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>)</span>
<span id="cb8-15">sweep_fold <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(fold_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(fc) {</span>
<span id="cb8-16">  o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(n_rep, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">offsets</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">share =</span> share_A, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> fc)))</span>
<span id="cb8-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> fc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(o)),</span>
<span id="cb8-18">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shareB =</span> share_A <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> fc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> share_A <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> share_A <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> fc))</span>
<span id="cb8-19">}))</span>
<span id="cb8-20">worst_norm_fold <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unlist</span>(sweep_fold[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MoR"</span>)])))</span>
<span id="cb8-21">worst_bound <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ceiling</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> worst_norm_fold) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb8-22">total_at_32 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>total[sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(fold_grid)]</span>
<span id="cb8-23">shareB_at_32 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>shareB[sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(fold_grid)]</span>
<span id="cb8-24">total_at_2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>total[sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> fold_grid[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb8-25">drop_at_32 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>total_at_32)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">fold_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb9-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>total, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total count (CPM)"</span>),</span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>TMM, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>),</span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> sweep_fold<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>MoR, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"median-of-ratios"</span>))</span>
<span id="cb9-5">fold_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(fold_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(fold_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling))</span>
<span id="cb9-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(fold_long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(fc, value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> scaling, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> scaling)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> sweep_fold, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(fc, expected), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inherit.aes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb9-9">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> scaling)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trans =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log2"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> fold_grid) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(magenta, violet, grey_dark), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_shape_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_linetype_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solid"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solid"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dotted"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fold change of the "</span>, n_changed, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" up genes (log scale)"</span>),</span>
<span id="cb9-16">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"median log2FC of unchanged genes"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-fold" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with the fold change of the up genes on a log scale on the x axis and the median log2 fold change of unchanged genes on the y axis. The total-count line falls steadily below zero and sits on a dashed curve showing the expected shift; the TMM and median-of-ratios lines stay flat at zero.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-fold-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/library-size-vs-composition/index_files/figure-html/fig-fold-1.png" class="img-fluid figure-img" alt="Line chart with the fold change of the up genes on a log scale on the x axis and the median log2 fold change of unchanged genes on the y axis. The total-count line falls steadily below zero and sits on a dashed curve showing the expected shift; the TMM and median-of-ratios lines stay flat at zero." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-fold-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Median log2 fold change of the unchanged genes as a handful of highly expressed genes are pushed further up. Total-count scaling follows the expected shift (dashed line); TMM and median-of-ratios stay near zero, where their lines lie on top of each other.
</figcaption>
</figure>
</div>
</div>
</div>
<p>At a 2-fold change the unchanged genes shift by only -0.07 under total-count scaling, small next to the gene-to-gene scatter in the MA plot. At 32-fold, where the up genes take 63% of the reads in condition B, the shift is -1.39, which is a 2.6-fold apparent drop for every other gene. Across the whole range TMM and median-of-ratios stay within 0.02 of zero.</p>
</section>
<section id="where-tmm-and-median-of-ratios-stop-working" class="level2">
<h2 class="anchored" data-anchor-id="where-tmm-and-median-of-ratios-stop-working">Where TMM and median-of-ratios stop working</h2>
<p>Both methods assume that most genes do not change, or that the changes up and down roughly balance. That assumption is the price of estimating the scaling from the genes themselves. To see what happens when it fails, the last simulation picks a growing fraction of genes at random and makes them all go up 3-fold, with no genes going down, averaging over 10 simulated datasets per setting.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>)</span>
<span id="cb10-2">frac_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb10-3">sweep_frac <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(frac_grid, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p) {</span>
<span id="cb10-4">  o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(n_rep_frac, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">offsets</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">up =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(n_genes, n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> p), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fc =</span> fc_frac)))</span>
<span id="cb10-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">frac =</span> p, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(o)))</span>
<span id="cb10-6">}))</span>
<span id="cb10-7">fr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, col) sweep_frac[sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>frac <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> p, col]</span>
<span id="cb10-8">tmm_at_05 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>); tot_at_05 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total"</span>)</span>
<span id="cb10-9">tmm_at_20 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>); mor_at_20 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MoR"</span>); tot_at_20 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total"</span>)</span>
<span id="cb10-10">tmm_at_50 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>); mor_at_50 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MoR"</span>); tot_at_50 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total"</span>)</span>
<span id="cb10-11">removed_05 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> tmm_at_05 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> tot_at_05     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># share of the shift that TMM removes</span></span>
<span id="cb10-12">removed_20 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> tmm_at_20 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> tot_at_20</span>
<span id="cb10-13">removed_50 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> tmm_at_50 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> tot_at_50</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">frac_long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(</span>
<span id="cb11-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">frac =</span> sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>frac, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>total, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total count (CPM)"</span>),</span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">frac =</span> sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>frac, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>TMM, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TMM"</span>),</span>
<span id="cb11-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">frac =</span> sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>frac, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> sweep_frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>MoR, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"median-of-ratios"</span>))</span>
<span id="cb11-5">frac_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(frac_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(frac_long<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaling))</span>
<span id="cb11-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(frac_long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> frac, value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> scaling, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> scaling)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> scaling)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(magenta, violet, grey_dark), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_shape_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_linetype_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solid"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solid"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dotted"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genes that go up "</span>, fc_frac, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-fold (%)"</span>),</span>
<span id="cb11-13">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"median log2FC of unchanged genes"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-fraction" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with the percentage of genes that go up on the x axis and the median log2 fold change of unchanged genes on the y axis. The total-count line falls steeply. The TMM and median-of-ratios lines start near zero and bend downwards as the percentage grows, ending not far above the total-count line.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-fraction-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/library-size-vs-composition/index_files/figure-html/fig-fraction-1.png" class="img-fluid figure-img" alt="Line chart with the percentage of genes that go up on the x axis and the median log2 fold change of unchanged genes on the y axis. The total-count line falls steeply. The TMM and median-of-ratios lines start near zero and bend downwards as the percentage grows, ending not far above the total-count line." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-fraction-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: The same measurement when a growing fraction of randomly chosen genes goes up, all in the same direction. Both composition-aware methods drift as the changed genes approach half of all genes.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With 5% of genes up, TMM leaves a shift of -0.03 against -0.13 for total-count scaling, removing 76% of the bias. With 20% of genes up it leaves -0.16 (median-of-ratios -0.19) against -0.48, which still removes most of it (66%). When half the genes go up, TMM is at -0.86 and median-of-ratios at -0.80, not far from the -1.01 of plain CPM: only 15% of the bias is removed. There is no majority of unchanged genes left to anchor on, and no method that uses only the sample’s own genes can tell “half the genes went up” from “the other half went down”.</p>
<p>Why does TMM already leave a shift at 5%, when it trims 30% from each tail? A 3-fold change is not extreme next to the noise of low-count genes, so many of the randomly chosen genes stay inside the untrimmed middle, and because they all move the same way they pull the trimmed mean and the median with them. The 20 genes of the first example escaped this because they were highly expressed and changed 10-fold.</p>
<p>A one-sided global change like this can happen, for example, when a treatment raises transcription across most of the genome. The reference then has to come from outside the genes being compared, usually spike-in RNA added in a fixed amount per cell. Spike-ins added per microgram of total RNA, a common way of using them, do not help here, because the total RNA is exactly what changed. DESeq2 can compute size factors from such a control set with the <code>controlGenes</code> argument of <code>estimateSizeFactors()</code>, and its vignette describes this case.</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>If you use edgeR, run <code>normLibSizes()</code> before anything that uses library sizes, and take CPM values from <code>cpm()</code> on the normalised object rather than from your own division by column sums:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb12-2">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group)</span>
<span id="cb12-3">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(d)</span>
<span id="cb12-4">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> d[keep, , keep.lib.sizes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>]</span>
<span id="cb12-5">d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(d)                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># TMM by default; calcNormFactors(d) in older code</span></span>
<span id="cb12-6">logcpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cpm</span>(d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># uses the TMM effective library sizes</span></span></code></pre></div></div>
<p><code>normLibSizes()</code> is the newer name for <code>calcNormFactors()</code>. Both exist in the edgeR version used here (4.8.2), the edgeR documentation says the two are equivalent and that <code>calcNormFactors()</code> will eventually be retired, and <code>normLibSizes()</code> first appeared in edgeR 3.42.0. The version guard at the top asks for edgeR 4.0.0 because of the <code>legacy</code> argument of <code>glmQLFit()</code>. The default method of <code>normLibSizes()</code> is TMM. The <code>cpm()</code> method for a <code>DGEList</code> has <code>normalized.lib.sizes = TRUE</code> by default, so after <code>normLibSizes()</code> it returns TMM-normalised CPM. <code>cpm(log = TRUE)</code> also adds a prior count before taking the log, which changes low-count genes in its own way; that is covered in <a href="https://pseudocount.com/posts/pseudocount-log-fold-change/">an earlier post</a>.</p>
<p>If you use DESeq2, the standard <code>DESeq()</code> call already estimates median-of-ratios size factors. For normalised values outside the test:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateSizeFactors</span>(dds)</span>
<span id="cb13-2">norm_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">counts</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">normalized =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
<p>Two habits catch the problem in real data. First, do not run a differential expression test on a table of CPM or TPM values exported from another tool: both are shares of each sample’s total and carry the same composition bias, and they have also lost the count information the tests need. Second, look at an MA plot after normalisation. If the dense cloud of genes is not centred on zero, either the normalisation was skipped or the assumption that most genes are unchanged does not hold for your experiment, and those two need different fixes. The reverse does not follow: TMM and median-of-ratios centre the bulk of genes by construction, so a centred plot cannot rule out a global shift. Only an external reference such as spike-ins can.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<p>Robinson MD, Oshlack A 2010 Genome Biology 11(3):R25 (<a href="https://doi.org/10.1186/gb-2010-11-3-r25">doi:10.1186/gb-2010-11-3-r25</a>)</p>
<p>Anders S, Huber W 2010 Genome Biology 11(10):R106 (<a href="https://doi.org/10.1186/gb-2010-11-10-r106">doi:10.1186/gb-2010-11-10-r106</a>)</p>
<p>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</p>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, edgeR 4.8.2,
generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0,
limma 3.66.0, MatrixGenerics 1.22.0, matrixStats 1.5.0, S4Vectors
0.48.1, Seqinfo 1.0.0, SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>normalisation</category>
  <category>RNA-seq</category>
  <category>edgeR</category>
  <category>DESeq2</category>
  <category>simulation</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/library-size-vs-composition/</guid>
  <pubDate>Thu, 03 Sep 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/library-size-vs-composition/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Batch confounded with condition: can correction help?</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/confounded-batch-and-condition/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(limma)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-6">})</span>
<span id="cb1-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"limma"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.58"</span>,</span>
<span id="cb1-8">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.40"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4"</span>)</span>
<span id="cb1-9">pct <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.*f%%"</span>, d, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-10">num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.*f"</span>, d, x)</span>
<span id="cb1-11">int <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb1-12">violet <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>; magenta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>; grey <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8797"</span></span>
<span id="cb1-13">theme_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>),</span>
<span id="cb1-15">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
</details>
</div>
<p>If batch and condition overlap in your RNA-seq experiment, can a batch correction step fix it? Only if batch and condition are not perfectly aligned (at least some batches hold both conditions), and only if the batch goes into the statistical model rather than being scrubbed out of the data beforehand. In the simulation below, a lopsided design analysed with limma and batch in the model keeps the false discovery proportion at 4.4%. Removing the batch first with <code>limma::removeBatchEffect()</code> and then testing the corrected values as if they were raw, same data and same limma test, pushes it to 34%. The honest analysis still pays for the lopsided layout in power: with edgeR, 68% of true changes are found, against 91% in a balanced layout. When batch and condition coincide completely, nothing can separate them.</p>
<p>First, two terms. A <em>batch</em> is any group of samples processed together, such as the same RNA extraction day or the same sequencing run. Two factors are <em>confounded</em> when they change together, so that the data cannot say which of them caused a difference.</p>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>Each simulated experiment has twelve samples: six controls and six treated, processed in two batches of six. Only the allocation of samples to batches changes between the three designs.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">mk <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(cond) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb2-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)),</span>
<span id="cb2-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cond  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(cond, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>)))</span>
<span id="cb2-4">designs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb2-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">balanced =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mk</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)),</span>
<span id="cb2-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">partial  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mk</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))),</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">full     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mk</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)))</span>
<span id="cb2-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(designs, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(d) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">condition =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>$balanced
     condition
batch ctrl trt
    A    3   3
    B    3   3

$partial
     condition
batch ctrl trt
    A    5   1
    B    1   5

$full
     condition
batch ctrl trt
    A    6   0
    B    0   6</code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">lay <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(designs), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(nm) {</span>
<span id="cb4-2">  d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> designs[[nm]]</span>
<span id="cb4-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> nm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cond =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond)</span>
<span id="cb4-4">}))</span>
<span id="cb4-5">lay<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(lay<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(designs)),</span>
<span id="cb4-6">                     <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partially confounded"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fully confounded"</span>)))</span>
<span id="cb4-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(lay, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(x, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> cond)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_tile</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">annotate</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">10.3</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.65</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch B"</span>),</span>
<span id="cb4-10">           <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey30"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrl =</span> grey, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trt =</span> violet), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condition"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.8</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>())</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-designs" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three rows of twelve tiles, split into batch A and batch B. In the balanced row each batch holds three control and three treated samples. In the partially confounded row batch A holds five controls and one treated sample and batch B the reverse. In the fully confounded row batch A is all control and batch B is all treated.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-designs-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/confounded-batch-and-condition/index_files/figure-html/fig-designs-1.png" class="img-fluid figure-img" alt="Three rows of twelve tiles, split into batch A and batch B. In the balanced row each batch holds three control and three treated samples. In the partially confounded row batch A holds five controls and one treated sample and batch B the reverse. In the fully confounded row batch A is all control and batch B is all treated." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-designs-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: The three sample layouts. Each row is one experiment of twelve samples split over two batches; colour shows the condition.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The counts are negative binomial, the usual model for RNA-seq read counts, for 3,000 genes. The first 300 genes have a true change between conditions, a log2 fold change of plus or minus 1; the rest have none. Every gene also gets a batch shift, drawn once per gene from a normal distribution with a standard deviation of 0.7 on the log2 scale, so batch B moves some genes up and others down. Library sizes differ a little between samples.</p>
<p>Two assumptions carry the argument. The batch effect adds to the condition effect on the log scale (it is the same in control and treated samples), and the batch labels are known. These are exactly the assumptions of a <code>~ batch + condition</code> model, so the model is given its best chance. The simulation is repeated 6 times; within each repeat, the three designs share the same genes and differ only in which samples sit in which batch.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">G <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3000</span></span>
<span id="cb5-2">n_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> G <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb5-3">true_lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>                                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log2 fold change of the DE genes</span></span>
<span id="cb5-4">batch_sd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>                                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># spread of per-gene log2 batch effects</span></span>
<span id="cb5-5">sim_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb5-6">  mu0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(G, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.3</span>))                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline mean count</span></span>
<span id="cb5-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu0 =</span> mu0,</span>
<span id="cb5-8">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.03</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(mu0),                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NB dispersion, higher for low counts</span></span>
<span id="cb5-9">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> true_lfc, n_de, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, G <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n_de)),</span>
<span id="cb5-10">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bfx =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(G, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, batch_sd))                    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log2 batch B effect, every gene</span></span>
<span id="cb5-11">}</span>
<span id="cb5-12">sim_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(g, d) {</span>
<span id="cb5-13">  lf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc, d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bfx, d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>)</span>
<span id="cb5-14">  mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu0 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>lf <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.25</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> G)</span>
<span id="cb5-15">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(G <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>phi), G, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span>
<span id="cb5-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">storage.mode</span>(m) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"integer"</span></span>
<span id="cb5-17">  m</span>
<span id="cb5-18">}</span>
<span id="cb5-19">is_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(G) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_de</span></code></pre></div></div>
</div>
</section>
<section id="full-confounding-is-not-a-statistics-problem" class="level2">
<h2 class="anchored" data-anchor-id="full-confounding-is-not-a-statistics-problem">Full confounding is not a statistics problem</h2>
<p>In the fully confounded design, the column of the design matrix that marks batch B is identical to the column that marks the treated samples. The matrix has three columns but only two independent ones, and no fitting procedure can split one number into two.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">X_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cond, designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full)</span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">columns =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(X_full), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rank =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qr</span>(X_full)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>rank)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>columns    rank 
      3       2 </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nonEstimable</span>(X_full)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "condtrt"</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>)</span>
<span id="cb10-2">cts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_counts</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_genes</span>(), designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full)</span>
<span id="cb10-3">deseq_msg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tryCatch</span>(</span>
<span id="cb10-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(cts, designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cond),</span>
<span id="cb10-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">error =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(e) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conditionMessage</span>(e))</span>
<span id="cb10-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(deseq_msg)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>the model matrix is not full rank, so the model cannot be fit as specified.
  One or more variables or interaction terms in the design formula are linear
  combinations of the others and must be removed.

  Please read the vignette section 'Model matrix not full rank':

  vignette('DESeq2')</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">edger_msg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tryCatch</span>({</span>
<span id="cb12-2">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(cts))</span>
<span id="cb12-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateDisp</span>(y, X_full)</span>
<span id="cb12-4">}, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">error =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(e) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conditionMessage</span>(e))</span>
<span id="cb12-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span>(edger_msg)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Design matrix not of full rank.  The following coefficients not estimable:
 condtrt</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># removeBatchEffect without group: what is left of the condition difference?</span></span>
<span id="cb14-2">lc_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cpm</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(cts), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prior.count =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb14-3">rb_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">removeBatchEffect</span>(lc_full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch,</span>
<span id="cb14-4">                             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(lc_full), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb14-5">max_diff_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(rb_full[, designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span></span>
<span id="cb14-6">                         <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(rb_full[, designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>])))</span>
<span id="cb14-7">max_diff_full</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 7.105427e-15</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... and with group: the warning is caught here so that it can be printed</span></span>
<span id="cb16-2">caught <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">character</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb16-3">rb_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">withCallingHandlers</span>(</span>
<span id="cb16-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">removeBatchEffect</span>(lc_full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond),</span>
<span id="cb16-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">warning =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(w) {</span>
<span id="cb16-6">    caught <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(caught, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">conditionMessage</span>(w)); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">invokeRestart</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"muffleWarning"</span>)</span>
<span id="cb16-7">  })</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Coefficients not estimable: batch1 </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">caught</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "Partial NA coefficients for 3000 probe(s)"</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1">max_change_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(rb_group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lc_full))</span>
<span id="cb20-2">max_change_group</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0</code></pre>
</div>
</div>
<p>Both packages refuse, and they are right to. DESeq2 stops as soon as the data object is built, with a message that the model matrix is not full rank; edgeR stops at dispersion estimation and names the coefficient it cannot estimate. limma’s <code>nonEstimable()</code> gives the same answer before any data are involved.</p>
<p>The tempting workarounds do not help. Dropping batch and fitting <code>~ condition</code> runs without complaint, but the “condition” coefficient is now condition plus batch: in the simulation, 86% of the genes called at 5% FDR (false discovery rate) have no true condition effect (Figure&nbsp;2). Running <code>removeBatchEffect()</code> on the data first is no better. Without the <code>group</code> argument, it removes the batch B shift, which is also the whole treatment difference: the largest remaining difference between condition means is 7.1e-15 log2 units, zero up to rounding error. With <code>group</code> supplied, the function reports that the batch coefficient cannot be estimated, issues a warning (caught and printed above), and returns the data unchanged: the largest change to any value is 0. Testing that output with <code>~ condition</code> is the first workaround again. Batch effects are widespread in high-throughput data, and when they line up with the biological groups they lead to wrong conclusions (Leek et al.&nbsp;2010).</p>
</section>
<section id="partial-confounding-put-batch-in-the-model" class="level2">
<h2 class="anchored" data-anchor-id="partial-confounding-put-batch-in-the-model">Partial confounding: put batch in the model</h2>
<p>In the other two designs every batch holds both conditions, so the model can estimate the batch shift from within-condition comparisons and the condition effect from within-batch comparisons. The analysis is edgeR’s quasi-likelihood pipeline (Chen et al.&nbsp;2016) in its current form. Filtering uses <code>filterByExpr()</code>, which according to its help page implements the filtering that paper describes informally, and normalisation uses <code>normLibSizes()</code> (a newer name for <code>calcNormFactors()</code>). <code>glmQLFit()</code> is called with <code>robust = TRUE</code>, as in the paper, and with <code>legacy = FALSE</code>, the new quasi-likelihood method that is the default from edgeR 4.2 onwards; in that mode <code>glmQLFit()</code> estimates the negative binomial dispersion itself, so no separate <code>estimateDisp()</code> step is needed. <code>glmQLFTest()</code> then tests the condition coefficient.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1">run_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(cts, X) {</span>
<span id="cb22-2">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(cts)</span>
<span id="cb22-3">  keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, X)</span>
<span id="cb22-4">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb22-5">  fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, X, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">robust =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb22-6">  res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>)</span>
<span id="cb22-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>logFC, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep =</span> keep)</span>
<span id="cb22-8">}</span>
<span id="cb22-9">score <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, de) {</span>
<span id="cb22-10">  called <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(p, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb22-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fpr   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>),                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># nulls with raw p &lt; 0.05</span></span>
<span id="cb22-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fdp   =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(called)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de[called]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># false discovery proportion</span></span>
<span id="cb22-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">power =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(called[de]))                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true DE genes called</span></span>
<span id="cb22-14">}</span></code></pre></div></div>
</div>
<p>The loop below runs every analysis in the post on each simulated experiment: the edgeR fits for this section, and the limma fits used in the next one.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1">n_rep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span></span>
<span id="cb23-2">runs1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb23-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ batch + cond"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ batch + cond"</span>),</span>
<span id="cb23-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ cond"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"full"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ cond"</span>))</span>
<span id="cb23-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>)</span>
<span id="cb23-6">res1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(); res2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(); nullp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>()</span>
<span id="cb23-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (r <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_rep)) {</span>
<span id="cb23-8">  g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_genes</span>()</span>
<span id="cb23-9">  cts_by <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(designs, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(d) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sim_counts</span>(g, d))</span>
<span id="cb23-10">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (k <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> runs1) {</span>
<span id="cb23-11">    d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> designs[[k[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]]</span>
<span id="cb23-12">    e <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_edger</span>(cts_by[[k[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.formula</span>(k[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]), d))</span>
<span id="cb23-13">    res1[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(res1) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rep =</span> r, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> k[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">model =</span> k[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>],</span>
<span id="cb23-14">                                           <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p, is_de[e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>keep])))</span>
<span id="cb23-15">  }</span>
<span id="cb23-16">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># next section: limma-trend on log-CPM, batch in the model vs removeBatchEffect first</span></span>
<span id="cb23-17">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (nm <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>)) {</span>
<span id="cb23-18">    d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> designs[[nm]]</span>
<span id="cb23-19">    X2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cond, d); X1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> cond, d)</span>
<span id="cb23-20">    y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(cts_by[[nm]])</span>
<span id="cb23-21">    keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, X2)</span>
<span id="cb23-22">    y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb23-23">    lc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cpm</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prior.count =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb23-24">    fits <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb23-25">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch in model"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eBayes</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lmFit</span>(lc, X2), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb23-26">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"removeBatchEffect with group"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eBayes</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lmFit</span>(</span>
<span id="cb23-27">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">removeBatchEffect</span>(lc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond), X1), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb23-28">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"removeBatchEffect without group"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eBayes</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lmFit</span>(</span>
<span id="cb23-29">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">removeBatchEffect</span>(lc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(lc), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),</span>
<span id="cb23-30">        X1), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>))</span>
<span id="cb23-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (m <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(fits)) {</span>
<span id="cb23-32">      p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fits[[m]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>]</span>
<span id="cb23-33">      lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fits[[m]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coefficients[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>]</span>
<span id="cb23-34">      de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> is_de[keep]</span>
<span id="cb23-35">      res2[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(res2) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rep =</span> r, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> nm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> m,</span>
<span id="cb23-36">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p, de)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc_de =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(lfc[de])))</span>
<span id="cb23-37">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (nm <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>) nullp[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(nullp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> p[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>de])</span>
<span id="cb23-38">    }</span>
<span id="cb23-39">  }</span>
<span id="cb23-40">}</span>
<span id="cb23-41">res1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, res1); res2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, res2); nullp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, nullp)</span>
<span id="cb23-42">agg1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aggregate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(fpr, fdp, power) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> design <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> model, res1, mean)</span>
<span id="cb23-43">agg2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aggregate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(fpr, fdp, power, lfc_de) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> design <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> method, res2, mean)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1">a1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(d, m, v) agg1[agg1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>design <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> agg1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> m, v]</span>
<span id="cb24-2">pow_bal  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a1</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ batch + cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>)</span>
<span id="cb24-3">pow_par  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a1</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ batch + cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>)</span>
<span id="cb24-4">fdp_bal  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a1</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ batch + cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>)</span>
<span id="cb24-5">fdp_par  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a1</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ batch + cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>)</span>
<span id="cb24-6">fdp_par_nob <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a1</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>)</span>
<span id="cb24-7">fdp_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a1</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"full"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>)</span>
<span id="cb24-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># precision of the condition coefficient: diagonal of (X'X)^-1, in units of sigma^2</span></span>
<span id="cb24-9">vf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(designs[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(d) {</span>
<span id="cb24-10">  X <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cond, d); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">solve</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">crossprod</span>(X))[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>] })</span>
<span id="cb24-11">se_ratio <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(vf[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> vf[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>])</span>
<span id="cb24-12">n_equiv  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> vf[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>]            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># per-group n of an unconfounded design with equal precision</span></span>
<span id="cb24-13">agg1</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>    design          model        fpr        fdp     power
1 balanced ~ batch + cond 0.05025914 0.03471029 0.9057948
2  partial ~ batch + cond 0.04960208 0.04436586 0.6817737
3     full         ~ cond 0.56486524 0.85723246 0.7711475
4  partial         ~ cond 0.29171683 0.60200705 0.7002244</code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1">lab1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">~ batch + cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partially confounded</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">~ batch + cond"</span>,</span>
<span id="cb26-2">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partially confounded</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">~ cond"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fully confounded</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">~ cond"</span>)</span>
<span id="cb26-3">nice <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">balanced =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">partial =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partially confounded"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">full =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fully confounded"</span>)</span>
<span id="cb26-4">res1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>analysis <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(nice[res1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>design], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, res1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(lab1))</span>
<span id="cb26-5">long1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(res1[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"analysis"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rep"</span>)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> res1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>power),</span>
<span id="cb26-6">               <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(res1[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"analysis"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rep"</span>)], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false discovery proportion"</span>,</span>
<span id="cb26-7">                          <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> res1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fdp))</span>
<span id="cb26-8">long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>metric <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>metric, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false discovery proportion"</span>))</span>
<span id="cb26-9">long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ok <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grepl</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch"</span>, long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>analysis)</span>
<span id="cb26-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(long1, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(value, analysis, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> ok)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_vline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false discovery proportion"</span>,</span>
<span id="cb26-12">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>metric)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>),</span>
<span id="cb26-13">             <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xintercept =</span> x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_blank</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>metric)),</span>
<span id="cb26-15">                              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">analysis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(long1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>analysis)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ok =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">position_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.12</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> metric, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scales =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"free_x"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">TRUE</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FALSE</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">guide =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.spacing =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unit</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lines"</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-part1" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two dot plots with four analyses each. With batch in the model, the balanced design has the highest power and the partially confounded design lower power, and both keep the false discovery proportion near the dashed 5% line. Leaving batch out in the partially confounded design, or analysing the fully confounded design with condition only, gives false discovery proportions far above the line.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-part1-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/confounded-batch-and-condition/index_files/figure-html/fig-part1-1.png" class="img-fluid figure-img" alt="Two dot plots with four analyses each. With batch in the model, the balanced design has the highest power and the partially confounded design lower power, and both keep the false discovery proportion near the dashed 5% line. Leaving batch out in the partially confounded design, or analysing the fully confounded design with condition only, gives false discovery proportions far above the line." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-part1-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Power (left) and false discovery proportion (right) for edgeR quasi-likelihood tests at a 5% FDR cut-off. Each dot is one simulated experiment; the dashed line marks the nominal 5%.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With <code>~ batch + condition</code>, both designs keep the false discovery proportion close to the 5% target on average (3.5% balanced, 4.4% partially confounded). The price of the lopsided layout is power: 91% of the truly changed genes are found in the balanced design and 68% in the partially confounded one, from the same number of samples.</p>
<p>The loss follows from the design alone. The variance of the condition estimate is the residual variance times a factor that depends only on the design matrix (the matching diagonal entry of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false" form="prefix">(</mo><msup><mi>X</mi><mi>⊤</mi></msup><mi>X</mi><msup><mo stretchy="false" form="postfix">)</mo><mrow><mi>−</mi><mn>1</mn></mrow></msup></mrow><annotation encoding="application/x-tex">(X^\top X)^{-1}</annotation></semantics></math>). That factor is 0.33 for the balanced design and 0.60 for the partial one, so the standard error is 1.34 times larger. The only information about the treatment effect comes from comparisons inside a batch, and in batch A that means five controls against a single treated sample. Twelve samples laid out this way estimate the condition effect about as precisely as an unconfounded design with 3.3 samples per group.</p>
<p>Leaving batch out of the partial design is worse than a loss of power. Now the batch shift leaks into the condition estimate, and 60% of the calls are false.</p>
</section>
<section id="correcting-first-testing-later" class="level2">
<h2 class="anchored" data-anchor-id="correcting-first-testing-later">Correcting first, testing later</h2>
<p>A common shortcut is to “clean” the data once and then run the differential expression (DE) test on the result: compute log-CPM values (log counts per million), remove the batch with <code>limma::removeBatchEffect()</code>, and pass the corrected matrix to <code>lmFit()</code> with <code>~ condition</code> as if it were ordinary data. The comparison uses limma (Ritchie et al.&nbsp;2015) in its limma-trend form: <code>lmFit()</code> on the log-CPM values, then <code>eBayes(trend = TRUE)</code>. The <code>eBayes()</code> help page recommends limma-trend for RNA-seq log-CPM values when library sizes are reasonably consistent, as they are here. Batch is either in the design matrix or removed beforehand. <code>removeBatchEffect()</code> is run two ways. With <code>group = condition</code>, the function fits batch and condition together and removes only the batch part, which is how its help page says to protect the effect of interest. Without <code>group</code>, the batch is estimated on its own.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb27-1">a2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(d, m, v) agg2[agg2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>design <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> agg2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> m, v]</span>
<span id="cb27-2">m0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch in model"</span>; mg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"removeBatchEffect with group"</span>; mn <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"removeBatchEffect without group"</span></span>
<span id="cb27-3">fpr_model_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, m0, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>); fpr_g_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, mg, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>)</span>
<span id="cb27-4">fpr_n_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, mn, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>)</span>
<span id="cb27-5">fdp_model_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, m0, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>); fdp_g_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, mg, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fdp"</span>)</span>
<span id="cb27-6">pow_model_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, m0, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>); pow_g_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, mg, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>)</span>
<span id="cb27-7">pow_n_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, mn, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"power"</span>)</span>
<span id="cb27-8">lfc_model_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, m0, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lfc_de"</span>); lfc_n_par <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>, mn, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lfc_de"</span>)</span>
<span id="cb27-9">fpr_model_bal <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, m0, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>); fpr_g_bal <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, mg, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>)</span>
<span id="cb27-10">fpr_n_bal <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">a2</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, mn, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>)</span>
<span id="cb27-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># with group: the naive fit uses (X1'X1)^-1 instead of the full-model variance factor</span></span>
<span id="cb27-12">X1p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> cond, designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial)</span>
<span id="cb27-13">t_inflate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(vf[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"partial"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">solve</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">crossprod</span>(X1p))[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>])</span>
<span id="cb27-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># without group: share of the condition contrast left after regressing on batch alone</span></span>
<span id="cb27-15">gp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>)</span>
<span id="cb27-16">keep_share <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resid</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lm</span>(gp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>((gp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(gp))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb27-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># check on the last partial experiment: same estimate, one residual df more, smaller SE</span></span>
<span id="cb27-18">lc_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cpm</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(cts_by<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prior.count =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb27-19">X2p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> cond, designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial)</span>
<span id="cb27-20">fit_full  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lmFit</span>(lc_p, X2p)</span>
<span id="cb27-21">fit_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lmFit</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">removeBatchEffect</span>(lc_p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch,</span>
<span id="cb27-22">                                     <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> designs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>partial<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cond), X1p)</span>
<span id="cb27-23">est_diff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(fit_full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coefficients[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> fit_naive<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coefficients[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condtrt"</span>]))</span>
<span id="cb27-24">df_full <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fit_full<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df.residual[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]; df_naive <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fit_naive<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>df.residual[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb27-25">agg2</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>    design                          method         fpr        fdp      power
1 balanced                  batch in model 0.047814449 0.02823014 0.90183235
2  partial                  batch in model 0.049665731 0.04375510 0.66448768
3 balanced    removeBatchEffect with group 0.060334592 0.04617665 0.91649528
4  partial    removeBatchEffect with group 0.162727008 0.34317329 0.89826435
5 balanced removeBatchEffect without group 0.060334592 0.04617665 0.91649528
6  partial removeBatchEffect without group 0.007460888 0.00000000 0.07046143
     lfc_de
1 0.9764442
2 0.9710172
3 0.9764442
4 0.9710172
5 0.9764442
6 0.5394540</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb29-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">t_inflate =</span> t_inflate, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep_share =</span> keep_share, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">est_diff =</span> est_diff,</span>
<span id="cb29-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df_full =</span> df_full, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df_naive =</span> df_naive)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>t_inflate.partial        keep_share          est_diff           df_full 
     1.341641e+00      5.555556e-01      3.774758e-15      9.000000e+00 
         df_naive 
     1.000000e+01 </code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb31-1">nullp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(nullp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(m0, mg, mn),</span>
<span id="cb31-2">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch in model"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"removeBatchEffect</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">with group"</span>,</span>
<span id="cb31-3">                                  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"removeBatchEffect</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">without group"</span>))</span>
<span id="cb31-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(nullp, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> method <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch in model"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb31-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb31-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb31-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">TRUE</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FALSE</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">guide =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb31-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"null genes"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-nullp" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three histograms of null p-values. With batch in the limma model the histogram is flat. After removeBatchEffect with the group argument the histogram has a tall spike near zero. After removeBatchEffect without the group argument the histogram is tilted towards one, with few small p-values.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-nullp-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/confounded-batch-and-condition/index_files/figure-html/fig-nullp-1.png" class="img-fluid figure-img" alt="Three histograms of null p-values. With batch in the limma model the histogram is flat. After removeBatchEffect with the group argument the histogram has a tall spike near zero. After removeBatchEffect without the group argument the histogram is tilted towards one, with few small p-values." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-nullp-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: P-values of genes with no true condition effect in the partially confounded design, pooled over all simulated experiments. A correct test gives a flat histogram.
</figcaption>
</figure>
</div>
</div>
</div>
<p>In the partially confounded design the two shortcuts fail in opposite directions. With batch in the model, 5.0% of the genes without a true effect have p &lt; 0.05, as a valid test should. After <code>removeBatchEffect()</code> with <code>group</code>, that share is 16.3%, and 34% of the genes called at 5% FDR are false. The same analysis appears to find 90% of the true changes, against 66% with batch in the model; that extra power is bought with the inflated error rate, not with information.</p>
<p>The reason is bookkeeping. After the correction, the condition estimate is the same number the full model would give (the largest difference over all genes in the last simulated experiment is 3.8e-15), but the second fit does not know that a batch effect was estimated from these twelve samples. It computes the standard error of a plain six-against-six comparison, which is too small by the factor of 1.34 from the previous section, and it counts 10 residual degrees of freedom where the full model has 9. Each t-statistic grows by that factor, and a little more for the extra degree of freedom, so in the histogram the null p-values pile up near zero. Nygaard et al.&nbsp;(2016) describe this effect for batch adjustment methods that retain group differences when groups are unevenly spread across batches.</p>
<p>Without <code>group</code>, the failure is loss of signal. The batch estimate is simply the difference between batch means, and with five treated samples in batch B, part of that difference is the treatment. Subtracting it leaves 56% of the true condition difference; the median estimated absolute log2 fold change of the truly changed genes drops to 0.54, against 0.97 with batch in the model (the truth is 1). Only 7% of true changes are found, and just 0.7% of null genes reach p &lt; 0.05.</p>
<p>In the balanced design, the two versions of <code>removeBatchEffect()</code> give identical results, because batch and condition are unrelated, and the damage is smaller: 6.0% of null genes reach p &lt; 0.05, against 4.8% with batch in the model. The excess comes from the extra degree of freedom alone. Balance limits the harm of the shortcut but does not make it correct.</p>
<p>The limma documentation says as much. The help page for <code>removeBatchEffect()</code> (limma 3.66.0, the version used here) describes it as a tool for plotting and exploration, such as PCA, MDS plots or heatmaps. Its note states that it is not meant to prepare data for linear modelling with <code>lmFit()</code>, and that batch factors should go into the linear model so that the standard errors are assessed correctly.</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>Fix the layout before the samples are processed. Spread every condition over every batch, as evenly as the sample numbers allow. If extraction or library preparation has to happen over several days, each day should include samples from each group. Check the layout from the sample sheet before sequencing:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb32-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>condition)          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># every cell should be non-zero</span></span>
<span id="cb32-2">X <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> condition, samples)</span>
<span id="cb32-3">limma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nonEstimable</span>(X)                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NULL means every coefficient can be estimated</span></span></code></pre></div></div>
<p>Analyse with batch in the design formula, in whichever package you use:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb33-1">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(counts, samples, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> condition)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2</span></span>
<span id="cb33-2">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> batch <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> condition, samples)                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR, limma</span></span></code></pre></div></div>
<p>Use <code>removeBatchEffect()</code> for pictures only, with the design so that the condition difference stays visible, and keep the uncorrected counts for testing:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(counts))</span>
<span id="cb34-2">logcpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cpm</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prior.count =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb34-3">design_cond <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> condition, samples)</span>
<span id="cb34-4">limma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plotMDS</span>(limma<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">removeBatchEffect</span>(logcpm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch =</span> samples<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">design =</span> design_cond))</span></code></pre></div></div>
<p>If the design is already fully confounded, no software step can recover the condition effect; the honest report says so. Adding new samples of each condition to the other batch turns it into a partially confounded design, which the model can analyse. Re-processing the same biological samples does not count as new samples: repeated libraries of one sample are technical replicates and must be handled as such (for example summed with <code>edgeR::sumTechReps()</code>), not added as independent replicates.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<p>Leek JT, Scharpf RB, Corrada Bravo H et al.&nbsp;2010 Nature Reviews Genetics 11(10):733-739 (<a href="https://doi.org/10.1038/nrg2825">doi:10.1038/nrg2825</a>)</p>
<p>Nygaard V, Rodland EA, Hovig E 2016 Biostatistics 17(1):29-39 (<a href="https://doi.org/10.1093/biostatistics/kxv027">doi:10.1093/biostatistics/kxv027</a>)</p>
<p>Ritchie ME, Phipson B, Wu D et al.&nbsp;2015 Nucleic Acids Research 43(7):e47 (<a href="https://doi.org/10.1093/nar/gkv007">doi:10.1093/nar/gkv007</a>)</p>
<p>Chen Y, Lun ATL, Smyth GK 2016 F1000Research 5:1438 (<a href="https://doi.org/10.12688/f1000research.8987.2">doi:10.12688/f1000research.8987.2</a>)</p>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, edgeR 4.8.2,
generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges 2.44.0,
limma 3.66.0, MatrixGenerics 1.22.0, matrixStats 1.5.0, S4Vectors
0.48.1, Seqinfo 1.0.0, SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>batch effects</category>
  <category>experimental design</category>
  <category>edgeR</category>
  <category>limma</category>
  <category>RNA-seq</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/confounded-batch-and-condition/</guid>
  <pubDate>Mon, 31 Aug 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/confounded-batch-and-condition/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Pseudobulk vs cell-level DE tests in scRNA-seq</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(Seurat)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(Matrix)</span>
<span id="cb1-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-7">})</span>
<span id="cb1-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Seurat"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"5.0.0"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>,</span>
<span id="cb1-9">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.40.0"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4.0"</span>,</span>
<span id="cb1-10">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Matrix"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.6.0"</span>)</span>
<span id="cb1-11">alpha <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>                                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># significance and FDR threshold</span></span>
<span id="cb1-12">violet <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>; magenta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>; grey <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a8799"</span></span></code></pre></div></div>
</details>
</div>
<p>You have single-cell RNA-seq data from treated and control samples and you want the genes that respond to treatment. The quickest route is to put all treated cells in one group and all control cells in the other, then test gene by gene. In Seurat that is <code>FindMarkers()</code>, whose default is a Wilcoxon rank-sum test on log-normalised expression. So the question people type into a search box is: can I treat cells as replicates?</p>
<p>Not when the conditions come from different donors (or mice, or cultures). In the simulation below, with 3 donors per condition and 300 cells per donor, the cell-level Wilcoxon test gave p &lt; 0.05 for 54% of the genes that have no true effect. Summing the counts per donor first (a <em>pseudobulk</em>) and testing with edgeR gave 4.4%, close to the 5% a p &lt; 0.05 threshold promises.</p>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">simulate_sc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_genes =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_de =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donors_per_group =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb2-2">                        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cells_per_donor =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor_sd =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">phi =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>) {</span>
<span id="cb2-3">  n_donor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> donors_per_group</span>
<span id="cb2-4">  donor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d%d"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_donor)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> cells_per_donor))</span>
<span id="cb2-5">  donor_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> donors_per_group))</span>
<span id="cb2-6">  group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> donor_group[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(donor)]</span>
<span id="cb2-7">  mu <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline mean UMI per cell</span></span>
<span id="cb2-8">  is_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_de                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the first n_de genes truly change</span></span>
<span id="cb2-9">  beta <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(is_de, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), n_genes, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lfc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb2-10">  b <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_donor, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, donor_sd), n_genes, n_donor)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># donor effects</span></span>
<span id="cb2-11">  size <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(donor), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>))          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cell-to-cell capture efficiency</span></span>
<span id="cb2-12">  trt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>)</span>
<span id="cb2-13">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> mu <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(b[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(donor)] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(beta, trt))</span>
<span id="cb2-14">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sweep</span>(m, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, size, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*"</span>)</span>
<span id="cb2-15">  counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(m), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi), n_genes)</span>
<span id="cb2-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dimnames</span>(counts) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"g%04d"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_genes)),</span>
<span id="cb2-17">                           <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c%05d"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(donor)))</span>
<span id="cb2-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">counts =</span> counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor =</span> donor, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> is_de)</span>
<span id="cb2-19">}</span>
<span id="cb2-20"></span>
<span id="cb2-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-22">sim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_sc</span>()</span>
<span id="cb2-23">n_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts); n_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de); n_null <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_genes <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n_de</span>
<span id="cb2-24">n_cells <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts); cells_per_donor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_cells <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nlevels</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor)</span>
<span id="cb2-25">n_per_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(simulate_sc)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donors_per_group</span>
<span id="cb2-26">donor_sd_main <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(simulate_sc)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor_sd</span>
<span id="cb2-27">donor_shift <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(donor_sd_main) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one sd up, as a ratio</span></span>
<span id="cb2-28">donor_shift_down <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>donor_sd_main)         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one sd down</span></span>
<span id="cb2-29">fold <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(simulate_sc)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc</span>
<span id="cb2-30">share_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</div>
<p>The simulated experiment is one cell type from 6 donors, 3 control and 3 treated, with 300 cells each (1,800 cells in total) and 2,000 genes. Counts follow a negative binomial distribution, the usual model for UMI counts. Each gene’s expression is built from a baseline level (72% of genes average less than one UMI per cell, a few average many), a donor effect, and cell-to-cell noise that includes differences in how many molecules each cell captured.</p>
<p>The donor effect is the assumption that matters. Each donor’s level of each gene is shifted up or down at random, with a standard deviation of 0.3 on the natural log scale: one standard deviation puts a donor about 35% above or 26% below the average for a given gene. Real donors differ like this for reasons unrelated to the treatment, such as genotype or the time from sampling to dissociation. How large the effect is depends on the tissue and the organism (inbred mice usually vary less than human donors), so the sweep further down also runs the case with no donor variation at all.</p>
<p>The first 200 genes get a true treatment effect, a 2-fold change up or down. The other 1,800 genes have no treatment effect, so any of them that a test calls significant is a false positive.</p>
<p>Figure&nbsp;1 shows what the donor effect looks like for one gene with no true effect. It is not the worst case: among the well-expressed null genes it is the one at the 90th percentile of the gap between treated and control donor means.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">so <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CreateSeuratObject</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CsparseMatrix"</span>),</span>
<span id="cb3-2">                         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">meta.data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group,</span>
<span id="cb3-3">                                                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts)))</span>
<span id="cb3-4">so <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">NormalizeData</span>(so, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">verbose =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)             <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># LogNormalize, scale factor 1e4</span></span>
<span id="cb3-5">lognorm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">GetAssayData</span>(so, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">layer =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>))</span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a well-expressed null gene whose donor means happen to separate by condition</span></span>
<span id="cb3-8">null_ids <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb3-9">donor_means <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">split</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_cells), sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor),</span>
<span id="cb3-10">                      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(j) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(lognorm[null_ids, j, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">drop =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>]))</span>
<span id="cb3-11">gap <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(donor_means[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(donor_means[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>])</span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># not the most extreme gene: the one at the 90th percentile of the treated-minus-control gap</span></span>
<span id="cb3-13">pick_q <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span></span>
<span id="cb3-14">gene_show <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(gap)[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.min</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(gap <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(gap, pick_q)))]</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">d1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">expr =</span> lognorm[gene_show, ], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group)</span>
<span id="cb4-2">d1m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aggregate</span>(expr <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> donor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> group, d1, mean)</span>
<span id="cb4-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(d1, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(donor, expr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> group)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">position_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb4-5">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_crossbar</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> d1m, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymin =</span> expr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymax =</span> expr), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>,</span>
<span id="cb4-7">                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrl =</span> grey, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trt =</span> violet)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log-normalised expression"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>,</span>
<span id="cb4-10">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(gene_show, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(no true effect)"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">guides</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">guide_legend</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">override.aes =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-one-gene" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Jittered points of log-normalised expression for each donor, control donors in grey and treated donors in violet, with a black bar at each donor's mean; the donor means differ from donor to donor, and the treated group's average sits higher than the control group's although the gene has no true effect.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-one-gene-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/index_files/figure-html/fig-one-gene-1.png" class="img-fluid figure-img" alt="Jittered points of log-normalised expression for each donor, control donors in grey and treated donors in violet, with a black bar at each donor's mean; the donor means differ from donor to donor, and the treated group's average sits higher than the control group's although the gene has no true effect." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-one-gene-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: One gene with no true condition effect. Each column of points is one donor’s cells; the black bar is that donor’s mean. The cells of a donor share that donor’s level, so the treated donors can sit above the controls by chance.
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="the-common-way-cells-as-replicates" class="level2">
<h2 class="anchored" data-anchor-id="the-common-way-cells-as-replicates">The common way: cells as replicates</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">default_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(Seurat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>FindMarkers.default)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>test.use</span>
<span id="cb5-2">default_lfc  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(Seurat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>FindMarkers.default)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>logfc.threshold</span>
<span id="cb5-3"></span>
<span id="cb5-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Idents</span>(so) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span></span>
<span id="cb5-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">options</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Seurat.presto.wilcox.msg =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># silence the "install presto" hint</span></span>
<span id="cb5-6">fm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FindMarkers</span>(so, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ident.1 =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ident.2 =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>,</span>
<span id="cb5-7">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">logfc.threshold =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">min.pct =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># test every gene</span></span>
<span id="cb5-8">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">densify =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">verbose =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># densify: speed only</span></span>
<span id="cb5-9">fm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fm[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts), ]</span>
<span id="cb5-10">p_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_val</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">test.use =</span> default_test, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">logfc.threshold =</span> default_lfc)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>       test.use logfc.threshold 
       "wilcox"           "0.1" </code></pre>
</div>
</div>
<p><code>formals()</code> on the installed Seurat returns “wilcox” as the default <code>test.use</code>, the Wilcoxon rank-sum test. Two other defaults drop genes before any test is run, <code>logfc.threshold</code> (0.1 in this version) and <code>min.pct</code>; both are set to zero above so that every gene gets a p-value and the false positive rate is measured on all of them. <code>densify = TRUE</code> only changes the speed. If the presto package is installed, Seurat runs the same test through presto’s faster implementation, which computes the same statistic with the same tie and continuity corrections.</p>
<p>For the gene in Figure&nbsp;1, the cell-level test gives p = 5.5e-11. It compares 900 treated cells with 900 control cells, and with that many observations even a small shift between the two sets counts as overwhelming evidence. (The <code>+1</code> inside the log-normalisation is a pseudocount, which also affects log fold changes; see <a href="https://pseudocount.com/posts/pseudocount-log-fold-change/">the pseudocount post</a>.)</p>
</section>
<section id="the-better-way-pseudobulk" class="level2">
<h2 class="anchored" data-anchor-id="the-better-way-pseudobulk">The better way: pseudobulk</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">pb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">AggregateExpression</span>(so, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group.by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor"</span>,</span>
<span id="cb8-2">                                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return.seurat =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>RNA)</span>
<span id="cb8-3">pb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pb[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor)]</span>
<span id="cb8-4">pb_check <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(pb <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowsum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts), sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor))))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 0: plain sums</span></span>
<span id="cb8-5">pb_group <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pb) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d3"</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>))</span>
<span id="cb8-6">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> pb_group)</span>
<span id="cb8-7"></span>
<span id="cb8-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR quasi-likelihood</span></span>
<span id="cb8-9">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(pb, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> pb_group)</span>
<span id="cb8-10">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, design)</span>
<span id="cb8-11">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb8-12">fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">robust =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb8-13">qlf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb8-14">p_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA_real_</span>, n_genes), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(pb))</span>
<span id="cb8-15">p_edger[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(qlf)] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> qlf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue</span>
<span id="cb8-16"></span>
<span id="cb8-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2 standard workflow</span></span>
<span id="cb8-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">storage.mode</span>(pb) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"integer"</span></span>
<span id="cb8-19">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(pb, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> pb_group), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb8-20">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb8-21">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>))</span>
<span id="cb8-22">p_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pvalue</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">score <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padj =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(p, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BH"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">is_de =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de) {</span>
<span id="cb9-2">  ok <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(p)</span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fpr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(p[ok <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha),</span>
<span id="cb9-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fd =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb9-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">td =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(padj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> is_de, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb9-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tested =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(ok))</span>
<span id="cb9-7">}</span>
<span id="cb9-8">tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cell_wilcox =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_cell),</span>
<span id="cb9-9">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pb_edger    =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_edger),</span>
<span id="cb9-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pb_deseq2   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">score</span>(p_deseq, res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>padj))</span>
<span id="cb9-11">tab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(tab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">obs_fdr =</span> tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fd"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pmax</span>(tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fd"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"td"</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb9-12">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">power =</span> tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"td"</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_de)</span>
<span id="cb9-13">fd_bonf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(fm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_val_adj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de)    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Seurat's own Bonferroni column</span></span>
<span id="cb9-14">td_bonf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(fm<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_val_adj <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de)</span>
<span id="cb9-15">fpr_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_wilcox"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>]; fpr_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_edger"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>]</span>
<span id="cb9-16">fpr_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_deseq2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr"</span>]</span>
<span id="cb9-17">fd_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_wilcox"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fd"</span>]; td_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_wilcox"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"td"</span>]</span>
<span id="cb9-18">fd_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_edger"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fd"</span>]; td_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_edger"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"td"</span>]</span>
<span id="cb9-19">fd_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_deseq2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fd"</span>]; td_deseq <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_deseq2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"td"</span>]</span>
<span id="cb9-20">obs_fdr_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tab[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_wilcox"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"obs_fdr"</span>]</span>
<span id="cb9-21">n_null_sig_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(p_cell[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha)</span>
<span id="cb9-22">p_show_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> p_cell[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(gene_show, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts))]</span>
<span id="cb9-23">p_show_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> p_edger[[gene_show]]</span>
<span id="cb9-24">fmt_p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(p) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2g"</span>, p)</span>
<span id="cb9-25">n_sig_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fd_cell <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> td_cell</span>
<span id="cb9-26">fpr_ratio_cell <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> fpr_cell <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> alpha</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(tab, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>              fpr  fd  td tested obs_fdr power
cell_wilcox 0.542 879 190   2000   0.822 0.950
pb_edger    0.044   1  53   1995   0.019 0.265
pb_deseq2   0.048   5  76   2000   0.062 0.380</code></pre>
</div>
</div>
<p>The pseudobulk is a plain sum: <code>AggregateExpression()</code> adds up the raw counts of each donor’s cells (its result matches <code>rowsum()</code> on the count matrix; largest difference 0). That leaves 6 samples, one per donor, which is what a bulk RNA-seq tool expects. edgeR runs with its quasi-likelihood recipe (<code>filterByExpr</code>, <code>normLibSizes</code>, <code>glmQLFit</code> with <code>robust = TRUE</code>, <code>glmQLFTest</code>; Chen et al.&nbsp;2016) and DESeq2 with its standard <code>DESeq()</code> and <code>results()</code> (Love et al.&nbsp;2014). <code>legacy = FALSE</code> selects the quasi-likelihood method added in edgeR 4.0; it is set explicitly so that older and newer edgeR versions run the same method. For the gene in Figure&nbsp;1, pseudobulk edgeR gives p = 0.15.</p>
<p>Across all 1,800 null genes, the cell-level test gave p &lt; 0.05 for 976 of them, a false positive rate of 54%, about 11 times the nominal rate. The pseudobulk tests gave 4.4% (edgeR, on the genes that pass <code>filterByExpr</code>) and 4.8% (DESeq2). Figure&nbsp;2 shows the same thing as p-value histograms: for genes with no effect, a calibrated test gives a flat histogram, and the cell-level test does not.</p>
<p>What people act on is the list of significant genes. At a Benjamini-Hochberg FDR of 5%, the cell-level test reported 1,069 genes, of which 879 are null: an observed false discovery rate of 82% where 5% was promised. Seurat’s own <code>p_val_adj</code> column uses a Bonferroni correction over all genes, which is much stricter, and it still let through 367 null genes. The false discoveries from pseudobulk numbered 1 with edgeR and 5 with DESeq2 (Figure&nbsp;3).</p>
<p>The price is sensitivity. The cell-level test found 190 of the 200 truly changed genes; pseudobulk edgeR found 53 and DESeq2 76. With 3 donors per group, there is little information about how much donors vary, and a 2-fold change is often not distinguishable from donor noise. That is an accurate statement of what 3 donors can tell you. The cell-level test’s extra hits cannot be used, because they arrive mixed with 879 false ones and nothing in the output says which are which.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cell_wilcox =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cells as replicates</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(Seurat Wilcoxon)"</span>,</span>
<span id="cb12-2">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pb_edger =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pseudobulk</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(edgeR QL)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pb_deseq2 =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pseudobulk</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">(DESeq2)"</span>)</span>
<span id="cb12-3">dp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> lab[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_wilcox"</span>]], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> p_cell[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de]),</span>
<span id="cb12-4">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> lab[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_edger"</span>]], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> p_edger[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de]),</span>
<span id="cb12-5">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> lab[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pb_deseq2"</span>]], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> p_deseq[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>is_de]))</span>
<span id="cb12-6">dp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> dp[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(dp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p), ]</span>
<span id="cb12-7">dp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(dp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> lab)</span>
<span id="cb12-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dp, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(p)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">after_stat</span>(density)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>),</span>
<span id="cb12-10">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> violet, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value (null genes only)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"density"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-pvalues" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three histograms of null-gene p-values. The cell-level Wilcoxon panel has a very tall bar at the left edge; the pseudobulk edgeR and DESeq2 panels are roughly flat around the dashed uniform line.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-pvalues-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/index_files/figure-html/fig-pvalues-1.png" class="img-fluid figure-img" alt="Three histograms of null-gene p-values. The cell-level Wilcoxon panel has a very tall bar at the left edge; the pseudobulk edgeR and DESeq2 panels are roughly flat around the dashed uniform line." width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-pvalues-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: P-values of the genes with no true effect. Under a well-calibrated test they spread evenly between 0 and 1 (dashed line). The cell-level Wilcoxon test piles them up near zero; both pseudobulk tests stay close to flat.
</figcaption>
</figure>
</div>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">dd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(lab, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(lab)),</span>
<span id="cb13-2">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kind =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true discovery"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false discovery"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb13-3">                               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false discovery"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true discovery"</span>)),</span>
<span id="cb13-4">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"td"</span>], tab[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fd"</span>]))</span>
<span id="cb13-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(dd, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(n, method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> kind)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true discovery"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> violet, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false discovery"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> magenta)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genes with FDR &lt;"</span>, alpha), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-discoveries" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Horizontal stacked bars for three methods. The cell-level Wilcoxon bar is long and mostly magenta (false discoveries); the two pseudobulk bars are short and almost entirely violet (true discoveries).">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-discoveries-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/index_files/figure-html/fig-discoveries-1.png" class="img-fluid figure-img" alt="Horizontal stacked bars for three methods. The cell-level Wilcoxon bar is long and mostly magenta (false discoveries); the two pseudobulk bars are short and almost entirely violet (true discoveries)." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-discoveries-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Genes called significant at the Benjamini-Hochberg FDR threshold used in the text, split into truly changed genes and genes with no effect. The cell-level test finds almost every true gene and many more false ones.
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="why-more-cells-make-it-worse" class="level2">
<h2 class="anchored" data-anchor-id="why-more-cells-make-it-worse">Why more cells make it worse</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wilcoxon rank-sum test with tie correction and continuity correction (normal</span></span>
<span id="cb14-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># approximation), the same test FindMarkers runs, vectorised for the sweep below.</span></span>
<span id="cb14-3">wilcox_rows <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, in2) {</span>
<span id="cb14-4">  n2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(in2); n1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(in2) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n2; n <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> n2</span>
<span id="cb14-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(x)), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) {</span>
<span id="cb14-6">    r <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rank</span>(x[i, ])</span>
<span id="cb14-7">    ties <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tabulate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(r, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(r)))</span>
<span id="cb14-8">    u <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(r[in2]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (n2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb14-9">    s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(n1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> ((n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(ties<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> ties) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (n <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))))</span>
<span id="cb14-10">    z <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(u <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> s</span>
<span id="cb14-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pnorm</span>(z, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lower.tail =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb14-12">  }, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb14-13">}</span>
<span id="cb14-14">p_check <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wilcox_rows</span>(lognorm, sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>)</span>
<span id="cb14-15">wilcox_diff <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(p_check <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p_cell))</span>
<span id="cb14-16">wilcox_diff</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 3.330669e-16</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">wilcox_diff_txt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.0e"</span>, wilcox_diff)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">pseudobulk_edger <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(counts, donor, group) {</span>
<span id="cb17-2">  pb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowsum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(counts), donor))</span>
<span id="cb17-3">  g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> group[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pb), donor)]</span>
<span id="cb17-4">  design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> g)</span>
<span id="cb17-5">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(pb, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> g)</span>
<span id="cb17-6">  keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, design)</span>
<span id="cb17-7">  y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb17-8">  fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">robust =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb17-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>PValue</span>
<span id="cb17-10">}</span>
<span id="cb17-11">grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand.grid</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cells =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor_sd =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>))</span>
<span id="cb17-12">n_genes_sweep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span></span>
<span id="cb17-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb17-14">sweep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(grid)), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) {</span>
<span id="cb17-15">  s <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_sc</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_genes =</span> n_genes_sweep, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_de =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cells_per_donor =</span> grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cells[i],</span>
<span id="cb17-16">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor_sd =</span> grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor_sd[i])</span>
<span id="cb17-17">  x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log1p</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e4</span>)</span>
<span id="cb17-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cells =</span> grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cells[i], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">donor_sd =</span> grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor_sd[i],</span>
<span id="cb17-19">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cells as replicates (Wilcoxon)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pseudobulk (edgeR QL)"</span>),</span>
<span id="cb17-20">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fpr =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wilcox_rows</span>(x, s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha),</span>
<span id="cb17-21">                     <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pseudobulk_edger</span>(s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor, s<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha)))</span>
<span id="cb17-22">}))</span>
<span id="cb17-23">sw <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m, c, sd) sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fpr[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grepl</span>(m, sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cells <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> c <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span></span>
<span id="cb17-24">                                     sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sd]</span>
<span id="cb17-25">fpr_w_25 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sw</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wilcoxon"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>); fpr_w_400 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sw</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wilcoxon"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb17-26">fpr_w0_max <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fpr[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grepl</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wilcoxon"</span>, sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb17-27">fpr_pb_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fpr[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grepl</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>, sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>method)])</span>
<span id="cb17-28">cells_min <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span>(grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cells); cells_max <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(grid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cells)</span>
<span id="cb17-29">n_sweep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(grid)</span></code></pre></div></div>
</div>
<p>The cell-level test asks whether treated cells rank higher than control cells, and treats every cell as an independent observation. It answers that question correctly: these particular 900 treated cells do differ from these 900 control cells, because their donors differ. But the experiment asks whether the treatment changes expression in the population the donors came from, and for that question the replicates are the donors. There are 3 per group, however many cells each one contributes.</p>
<p>This predicts that more cells per donor should make the cell-level test worse, not better, and that without donor variation it should be fine. To check, the helper <code>wilcox_rows()</code> above reproduces the <code>FindMarkers()</code> p-values (largest absolute difference 3e-16) and is fast enough to rerun on 10 simulated data sets (one for each combination of cell count and donor variation in Figure&nbsp;4), each with 3 donors per group and 1,000 null genes.</p>
<p>Figure&nbsp;4 has the result. With no donor variation, the cell-level test stays calibrated: its false positive rate is close to the nominal rate, at most 6.2% at any cell count. With donor variation it climbs from 14% at 25 cells per donor to 58% at 400. Pseudobulk edgeR stays between 4.3% and 7.0% throughout, because summing more cells makes each donor’s total more precise without pretending there are more donors.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>panel <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor_sd <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no donor variation"</span>,</span>
<span id="cb18-2">                             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor variation (sd 0.3)"</span>),</span>
<span id="cb18-3">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no donor variation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor variation (sd 0.3)"</span>))</span>
<span id="cb18-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(sweep, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(cells, fpr, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> method)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> alpha, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> grey) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(sweep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cells)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(v) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> v, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(magenta, violet)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> panel) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cells per donor"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false positive rate"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-sweep" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two line-chart panels with cells per donor on a log axis. With no donor variation both methods sit near the nominal rate. With donor variation the cell-level Wilcoxon line climbs steeply as cells increase while the pseudobulk edgeR line stays near the nominal rate.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-sweep-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/index_files/figure-html/fig-sweep-1.png" class="img-fluid figure-img" alt="Two line-chart panels with cells per donor on a log axis. With no donor variation both methods sit near the nominal rate. With donor variation the cell-level Wilcoxon line climbs steeply as cells increase while the pseudobulk edgeR line stays near the nominal rate." width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-sweep-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;4: False positive rate on genes with no effect as the number of cells per donor grows. Left: donors identical apart from cell-level noise. Right: donors differ. The dashed line is the nominal rate.
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="the-same-check-in-python" class="level2">
<h2 class="anchored" data-anchor-id="the-same-check-in-python">The same check in Python</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1">py <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read.csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pseudobulk_check-results.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb19-2">pyv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>value, py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>name)</span>
<span id="cb19-3">py_num <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pyv[[k]])</span>
<span id="cb19-4">py_fpr_w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_wilcoxon"</span>); py_fpr_wt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_wilcoxon_tiecorr"</span>)</span>
<span id="cb19-5">py_fpr_d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_pydeseq2"</span>)</span>
<span id="cb19-6">py_fd_w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_disc_wilcoxon"</span>); py_td_w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true_disc_wilcoxon"</span>)</span>
<span id="cb19-7">py_fd_d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_disc_pydeseq2"</span>); py_td_d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true_disc_pydeseq2"</span>)</span>
<span id="cb19-8">py_n_d <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pydeseq2_n_datasets"</span>)</span>
<span id="cb19-9">py_fpr_d_min <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_pydeseq2_min"</span>); py_fpr_d_max <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_num</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_pydeseq2_max"</span>)</span>
<span id="cb19-10">py_scanpy <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pyv[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scanpy_version"</span>]]; py_pydeseq2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> pyv[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pydeseq2_version"</span>]]</span></code></pre></div></div>
</div>
<p>The script below runs the same comparison in scanpy and PyDESeq2 on an AnnData object simulated the same way, with numpy’s random generator (so the draws, and the exact numbers, differ from the R run). The numbers were computed with scanpy 1.11.5 and PyDESeq2 0.5.4 and are shown for comparison. <code>sc.tl.rank_genes_groups(..., method="wilcoxon")</code> gave p &lt; 0.05 for 46% of null genes; pseudobulk with PyDESeq2 gave 6.9%, a little above the nominal 5%. At an FDR of 5%, scanpy reported 728 false and 187 true discoveries, PyDESeq2 7 false and 73 true. The script also reruns the pseudobulk step on four more simulated data sets: across all 5, PyDESeq2’s false positive rate ranged from 5.9% to 6.9%. That is consistently a little above the nominal rate in this setup, and above the R DESeq2 run, but still far below the cell-level test. The cause was not traced here, so treat it as a difference between the two implementations at 3 samples per group rather than a property of pseudobulk. One difference from Seurat: scanpy’s Wilcoxon skips the correction for tied values by default (<code>tie_correct=False</code>), and single-cell data are full of tied zeros. Without the correction the test is more conservative; with it switched on, the false positive rate on the same data was 55%. Either way the problem is the same.</p>
<div class="cell" data-python.reticulate="false">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cells as replicates vs pseudobulk, in scanpy + PyDESeq2.</span></span>
<span id="cb20-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Same design as the R code in the post: 3 vs 3 donors, donor-level variation, 10% true DE genes.</span></span>
<span id="cb20-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Writes pseudobulk_check-results.csv (columns name,value).</span></span>
<span id="cb20-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> importlib.metadata <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> version</span>
<span id="cb20-5"></span>
<span id="cb20-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> anndata <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> ad</span>
<span id="cb20-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb20-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb20-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> scanpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sc</span>
<span id="cb20-10"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pydeseq2.dds <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DeseqDataSet</span>
<span id="cb20-11"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pydeseq2.ds <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DeseqStats</span>
<span id="cb20-12"></span>
<span id="cb20-13">n_genes, n_de, per_group, cells_per_donor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span></span>
<span id="cb20-14">donor_sd, phi, alpha <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span></span>
<span id="cb20-15">n_donor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> per_group</span>
<span id="cb20-16">is_de <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.arange(n_genes) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> n_de</span>
<span id="cb20-17"></span>
<span id="cb20-18"></span>
<span id="cb20-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> simulate(rng):</span>
<span id="cb20-20">    donor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.repeat([<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"d</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_donor)], cells_per_donor)</span>
<span id="cb20-21">    group <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.repeat(np.repeat([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>], per_group), cells_per_donor)</span>
<span id="cb20-22">    mu <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(rng.normal(np.log(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, n_genes))            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># baseline mean per cell</span></span>
<span id="cb20-23">    beta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(is_de, rng.choice([<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>], n_genes) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> np.log(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)</span>
<span id="cb20-24">    b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.normal(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, donor_sd, (n_donor, n_genes))              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># donor effects</span></span>
<span id="cb20-25">    size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(rng.normal(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, donor.size))                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cell size factors</span></span>
<span id="cb20-26">    d_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.repeat(np.arange(n_donor), cells_per_donor)</span>
<span id="cb20-27">    trt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (group <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>)</span>
<span id="cb20-28">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> size[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mu[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> np.exp(b[d_idx] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> trt[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> beta[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :])</span>
<span id="cb20-29">    counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.poisson(m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> rng.gamma(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> phi, phi, m.shape))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># negative binomial</span></span>
<span id="cb20-30">    adata <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ad.AnnData(</span>
<span id="cb20-31">        X<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>counts.astype(np.float32),</span>
<span id="cb20-32">        obs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor"</span>: donor, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>: group},</span>
<span id="cb20-33">                         index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"c</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:05d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(donor.size)]),</span>
<span id="cb20-34">        var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pd.DataFrame(index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"g</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:04d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_genes)]),</span>
<span id="cb20-35">    )</span>
<span id="cb20-36">    adata.layers[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"counts"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> adata.X.copy()                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep raw counts</span></span>
<span id="cb20-37">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> adata</span>
<span id="cb20-38"></span>
<span id="cb20-39"></span>
<span id="cb20-40"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> pseudobulk_deseq(adata):</span>
<span id="cb20-41">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sum RAW counts per donor, then PyDESeq2</span></span>
<span id="cb20-42">    pb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sc.get.aggregate(adata, by<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor"</span>, func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sum"</span>, layer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"counts"</span>)</span>
<span id="cb20-43">    counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(np.rint(pb.layers[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sum"</span>]).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>),</span>
<span id="cb20-44">                          index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pb.obs_names, columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>adata.var_names)</span>
<span id="cb20-45">    donor_group <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> adata.obs.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor"</span>, observed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>].first()</span>
<span id="cb20-46">    meta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>: donor_group.loc[counts.index].to_numpy()}, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>counts.index)</span>
<span id="cb20-47">    dds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DeseqDataSet(counts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>counts, metadata<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>meta, design<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~group"</span>, quiet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, n_cpus<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb20-48">    dds.deseq2()</span>
<span id="cb20-49">    st <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DeseqStats(dds, contrast<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>], quiet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, n_cpus<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb20-50">    st.summary()</span>
<span id="cb20-51">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> st.results_df.loc[adata.var_names]</span>
<span id="cb20-52">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pvalue"</span>].to_numpy(), res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"padj"</span>].to_numpy()</span>
<span id="cb20-53"></span>
<span id="cb20-54"></span>
<span id="cb20-55"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fpr(p):</span>
<span id="cb20-56">    ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>is_de <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>np.isnan(p)</span>
<span id="cb20-57">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(np.mean(p[ok] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha))</span>
<span id="cb20-58"></span>
<span id="cb20-59"></span>
<span id="cb20-60"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> count(q, which):</span>
<span id="cb20-61">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>((q <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> alpha) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> which <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>np.isnan(q)))</span>
<span id="cb20-62"></span>
<span id="cb20-63"></span>
<span id="cb20-64">adata <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> simulate(np.random.default_rng(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span>))</span>
<span id="cb20-65">genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> adata.var_names</span>
<span id="cb20-66"></span>
<span id="cb20-67"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cells as replicates: Wilcoxon on log-normalised expression</span></span>
<span id="cb20-68">cell <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> adata.copy()</span>
<span id="cb20-69">sc.pp.normalize_total(cell, target_sum<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e4</span>)</span>
<span id="cb20-70">sc.pp.log1p(cell)</span>
<span id="cb20-71">sc.tl.rank_genes_groups(cell, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>, groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>], reference<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wilcoxon"</span>)</span>
<span id="cb20-72">w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sc.get.rank_genes_groups_df(cell, group<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>).set_index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"names"</span>).loc[genes]</span>
<span id="cb20-73">p_w, q_w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> w[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pvals"</span>].to_numpy(), w[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pvals_adj"</span>].to_numpy()</span>
<span id="cb20-74"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># scanpy skips the tie correction by default (tie_correct=False); Seurat applies it</span></span>
<span id="cb20-75">sc.tl.rank_genes_groups(cell, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>, groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>], reference<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ctrl"</span>, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wilcoxon"</span>,</span>
<span id="cb20-76">                        tie_correct<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, key_added<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wilcoxon_ties"</span>)</span>
<span id="cb20-77">wt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sc.get.rank_genes_groups_df(cell, group<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trt"</span>, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wilcoxon_ties"</span>).set_index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"names"</span>)</span>
<span id="cb20-78">p_wt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> wt.loc[genes, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pvals"</span>].to_numpy()</span>
<span id="cb20-79"></span>
<span id="cb20-80"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pseudobulk + PyDESeq2</span></span>
<span id="cb20-81">p_d, q_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pseudobulk_deseq(adata)</span>
<span id="cb20-82"></span>
<span id="cb20-83"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># PyDESeq2 false positive rate on four more simulated data sets</span></span>
<span id="cb20-84">extra <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [fpr(pseudobulk_deseq(simulate(np.random.default_rng(s)))[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> s <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)]</span>
<span id="cb20-85">all_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [fpr(p_d)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> extra</span>
<span id="cb20-86"></span>
<span id="cb20-87">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb20-88">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_wilcoxon"</span>: fpr(p_w),</span>
<span id="cb20-89">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_wilcoxon_tiecorr"</span>: fpr(p_wt),</span>
<span id="cb20-90">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_pydeseq2"</span>: fpr(p_d),</span>
<span id="cb20-91">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_disc_wilcoxon"</span>: count(q_w, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>is_de),</span>
<span id="cb20-92">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false_disc_pydeseq2"</span>: count(q_d, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>is_de),</span>
<span id="cb20-93">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true_disc_wilcoxon"</span>: count(q_w, is_de),</span>
<span id="cb20-94">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true_disc_pydeseq2"</span>: count(q_d, is_de),</span>
<span id="cb20-95">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_de"</span>: n_de,</span>
<span id="cb20-96">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_null"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>is_de)),</span>
<span id="cb20-97">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pydeseq2_n_datasets"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_d),</span>
<span id="cb20-98">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_pydeseq2_min"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(all_d),</span>
<span id="cb20-99">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fpr_pydeseq2_max"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(all_d),</span>
<span id="cb20-100">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scanpy_version"</span>: version(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scanpy"</span>),</span>
<span id="cb20-101">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pydeseq2_version"</span>: version(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pydeseq2"</span>),</span>
<span id="cb20-102">}</span>
<span id="cb20-103">pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(rows), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(rows.values())}).to_csv(</span>
<span id="cb20-104">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pseudobulk_check-results.csv"</span>, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb20-105"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(pd.Series(rows))</span></code></pre></div></div>
</div>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>Decide what the replicate is before you analyse anything. It is the unit that was independently assigned to a condition or sampled from the population, such as a donor or an animal. Cells inside it are measurements of that unit, the way technical replicates are in a bulk experiment.</p>
<p>For differential expression between conditions, sum the raw counts per sample within each cell type, then run a bulk method the way its authors recommend. In Seurat, the loop looks like this (<code>celltype</code>, <code>donor</code> and <code>condition</code> are metadata columns you already have):</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (ct <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(so<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>celltype)) {</span>
<span id="cb21-2">  sub <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">subset</span>(so, celltype <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> ct)</span>
<span id="cb21-3">  pb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">AggregateExpression</span>(sub, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group.by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"donor"</span>,</span>
<span id="cb21-4">                                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">return.seurat =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>RNA)</span>
<span id="cb21-5">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># AggregateExpression() may rewrite group names (for example, adding a "g" before a</span></span>
<span id="cb21-6">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># leading digit), so check that every column found its donor</span></span>
<span id="cb21-7">  condition <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>condition[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(pb), sub<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>donor)]</span>
<span id="cb21-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">anyNA</span>(condition))</span>
<span id="cb21-9">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... then the edgeR block above, with condition in place of pb_group</span></span>
<span id="cb21-10">}</span></code></pre></div></div>
</div>
<p>In scanpy, <code>sc.get.aggregate(adata, by=["celltype", "donor"], func="sum", layer="counts")</code> does the summing (the sums land in <code>.layers["sum"]</code>); the <code>counts</code> layer must hold raw counts, not the log-normalised values that <code>X</code> usually holds after preprocessing. The script above uses the same call with <code>by="donor"</code>. If each donor contributes both conditions (before and after treatment, say), put the donor in the design, <code>~ donor + condition</code>, so the comparison is made within donors. The muscat package wraps pseudobulk aggregation per cluster and also offers cell-level mixed models, which keep the cells but model the donor as a random effect (Crowell et al.&nbsp;2020).</p>
<p>Keep cell-level tests for questions that really are about the cells in hand, such as which genes separate one cluster from another in the same samples. Seurat’s own <a href="https://satijalab.org/seurat/articles/de_vignette">differential expression vignette</a> makes the same point, noting that these tests treat each cell as an independent replicate, and shows a pseudobulk alternative. A large benchmark reached the same conclusion: methods that ignore variation between biological replicates find hundreds of genes in data with no biological difference (Squair et al.&nbsp;2021).</p>
<p>If pseudobulk gives you too few genes, the fix is more donors. Adding cells per donor does not add replicates.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Squair JW, Gautier M, Kathe C, et al.&nbsp;2021 Nature Communications 12(1):5692 (<a href="https://doi.org/10.1038/s41467-021-25960-2">doi:10.1038/s41467-021-25960-2</a>)</li>
<li>Crowell HL, Soneson C, Germain PL, et al.&nbsp;2020 Nature Communications 11(1):6077 (<a href="https://doi.org/10.1038/s41467-020-19894-4">doi:10.1038/s41467-020-19894-4</a>)</li>
<li>Chen Y, Lun ATL, Smyth GK 2016 F1000Research 5:1438 (<a href="https://doi.org/10.12688/f1000research.8987.2">doi:10.12688/f1000research.8987.2</a>)</li>
<li>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2, edgeR 4.8.2, future
1.76.0, generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3, IRanges
2.44.0, limma 3.66.0, Matrix 1.7.6, MatrixGenerics 1.22.0, matrixStats
1.5.0, S4Vectors 0.48.1, Seqinfo 1.0.0, Seurat 5.5.1, SeuratObject
5.4.0, sp 2.2.3, SummarizedExperiment 1.40.0
Python part: scanpy 1.11.5, pydeseq2 0.5.4</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>scRNA-seq</category>
  <category>pseudobulk</category>
  <category>Seurat</category>
  <category>edgeR</category>
  <category>scanpy</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/</guid>
  <pubDate>Thu, 27 Aug 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/pseudobulk-vs-cell-level-tests/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>What log2(x + 1) does to low-count fold changes</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/pseudocount-log-fold-change/</link>
  <description><![CDATA[ 





<div class="cell">
<details class="code-fold">
<summary>Setup: packages and helper functions</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb1-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DESeq2)</span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(edgeR)</span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(apeglm)</span>
<span id="cb1-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-6">})</span>
<span id="cb1-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.40"</span>,</span>
<span id="cb1-8">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4.0.0"</span>,</span>
<span id="cb1-9">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apeglm"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.20"</span>,</span>
<span id="cb1-10">          <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">packageVersion</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.4"</span>)</span>
<span id="cb1-11">f2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, x)</span>
<span id="cb1-12">f1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.1f"</span>, x)</span>
<span id="cb1-13">f0 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(x), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>)</span>
<span id="cb1-14">pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.0f%%"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x)</span>
<span id="cb1-15">theme_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb1-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_rect</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>),</span>
<span id="cb1-17">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>)</span></code></pre></div></div>
</details>
</div>
<p>You have a table of counts, you want a fold change, and the zeros get in the way: <code>log2(0)</code> is minus infinity. So you add 1, take <code>log2(count + 1)</code>, average each group and subtract. This is a very common shortcut in RNA-seq analysis, and the question behind it is simple: what does the added 1 do to the fold change?</p>
<p>The short answer: it pulls the fold changes of low-count genes towards zero, by an amount that depends on how many reads the gene has and on the constant you picked, not on how many samples you have. In the simulation below, genes whose true log2 fold change is 2 (a four-fold change) and whose mean count is between 2 and 5 reads come out at a median of 1.44 with <code>log2(count + 1)</code>. Measuring more samples does not fix it.</p>
<section id="the-setup" class="level2">
<h2 class="anchored" data-anchor-id="the-setup">The setup</h2>
<p>The simulation is deliberately plain. Each gene gets a mean count drawn on a log scale between half a read and a thousand reads, so every expression level is well represented. Most genes do not change; the rest go up or down by exactly a log2 fold change of 2. Counts are drawn from a negative binomial distribution, which is the usual model for RNA-seq counts: Poisson-like sampling noise plus biological variation between samples, set here by a dispersion parameter. The six samples differ a little in sequencing depth.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">n_genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4000</span>; n_rep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>; disp_sim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>; true_abs <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>; p_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span></span>
<span id="cb2-2"></span>
<span id="cb2-3">simulate_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">G =</span> n_genes, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> n_rep, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> disp_sim) {</span>
<span id="cb2-4">  mu  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(G, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)))       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># mean count of each gene</span></span>
<span id="cb2-5">  lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, true_abs, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>true_abs), G, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true log2 FC, B vs A</span></span>
<span id="cb2-6">                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prob =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p_de, p_de <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, p_de <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb2-7">  muA <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mu <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>lfc)                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the two group means average to mu</span></span>
<span id="cb2-8">  muB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> muA <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>lfc</span>
<span id="cb2-9">  sf  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep_len</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sequencing depth</span></span>
<span id="cb2-10">  M   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(muA, G, n), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(muB, G, n)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(sf, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> G)</span>
<span id="cb2-11">  counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnbinom</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(M), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> M, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> disp), G,</span>
<span id="cb2-12">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"g"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>G), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n))))</span>
<span id="cb2-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">storage.mode</span>(counts) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"integer"</span></span>
<span id="cb2-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">counts =</span> counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n)),</span>
<span id="cb2-15">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> lfc)</span>
<span id="cb2-16">}</span>
<span id="cb2-17"></span>
<span id="cb2-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># mean-count bins used to summarise the results</span></span>
<span id="cb2-19">brk <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)</span>
<span id="cb2-20">bin_lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0.5-2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2-5"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"5-10"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"10-30"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"30-100"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"100-1000"</span>)</span>
<span id="cb2-21"></span>
<span id="cb2-22"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260825</span>)</span>
<span id="cb2-23">sim <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>()</span>
<span id="cb2-24">n_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div></div>
</div>
<p>That gives 4,000 genes in 3 versus 3 samples, of which 1,142 truly change. A few things to keep in mind. The dispersion is the same for every gene (0.1); real data usually have more biological variation at low counts. That makes low-count estimates noisier, and, as the exact calculation further down shows, it makes the shortcut’s problem larger, not smaller. Every changed gene changes by the same amount, and the attenuation grows with the size of the true change. The share of unchanged genes (70%) sets how hard <code>apeglm</code> shrinks, so the error comparison near the end depends on it. Finally, genes are grouped by their true mean count, which we know because we simulated it; with real data the closest thing is DESeq2’s <code>baseMean</code> column.</p>
</section>
<section id="the-shortcut-add-a-constant-then-log" class="level2">
<h2 class="anchored" data-anchor-id="the-shortcut-add-a-constant-then-log">The shortcut: add a constant, then log</h2>
<p>Here is the shortcut, on counts normalised for sequencing depth with DESeq2’s size factors. The second version is the edgeR equivalent, log counts per million from <code>cpm(log = TRUE)</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">A <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>; B <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span></span>
<span id="cb3-2">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group)</span>
<span id="cb3-3">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateSizeFactors</span>(dds)</span>
<span id="cb3-4">norm_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">counts</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">normalized =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the common shortcut: log2(count + c), then difference of group means</span></span>
<span id="cb3-7">naive_lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x, c) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(x[, B] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(x[, A] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c))</span>
<span id="cb3-8">lfc_plus1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">naive_lfc</span>(norm_counts, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb3-9"></span>
<span id="cb3-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR log-CPM with its default prior.count</span></span>
<span id="cb3-11">y_all <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DGEList</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group))</span>
<span id="cb3-12">logcpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cpm</span>(y_all, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">log =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb3-13">lfc_logcpm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(logcpm[, B]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(logcpm[, A])</span>
<span id="cb3-14">prior_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>cpm.DGEList)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prior.count</span>
<span id="cb3-15"></span>
<span id="cb3-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a noise-free example: 1 read versus 4 reads</span></span>
<span id="cb3-17">ex_plus1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span></code></pre></div></div>
</div>
<p>Why should adding 1 matter? For a gene with thousands of reads it does not: 1 is nothing next to 2,000. For a gene with a handful of reads it is a large part of the value. A gene with exactly 1 read in one group and 4 in the other has a true log2 fold change of 2, but <code>log2(4 + 1) - log2(1 + 1)</code> is 1.32. The constant is added to both groups, so the ratio is dragged towards 1 and its logarithm towards 0.</p>
<p>The edgeR version adds a constant too. <code>cpm(..., log = TRUE)</code> has a default <code>prior.count</code> of 2, and its help page says this count is scaled in proportion to library size, so a sample of average depth gets 2 reads added before the log. That is more than 1, so expect more attenuation, not less.</p>
</section>
<section id="model-based-estimates" class="level2">
<h2 class="anchored" data-anchor-id="model-based-estimates">Model-based estimates</h2>
<p>The alternative is to estimate the fold change inside a count model. DESeq2 fits a negative binomial generalised linear model per gene (Love et al.&nbsp;2014); since version 1.16, <code>results()</code> reports the maximum likelihood estimate (MLE) of the log2 fold change without shrinkage, according to the DESeq2 vignette. <code>lfcShrink()</code> then adds a shrunken estimate.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb4-2">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_B_vs_A"</span>)                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># maximum likelihood LFC</span></span>
<span id="cb4-3">shr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lfcShrink</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_B_vs_A"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apeglm"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb4-4">shrink_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eval</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>lfcShrink)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>type)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span></code></pre></div></div>
</div>
<p>The default <code>type</code> of <code>lfcShrink()</code> is apeglm, the method used here.</p>
<p>For edgeR the recommended route is the quasi-likelihood pipeline (Chen et al.&nbsp;2016). In the edgeR QL workflow used here, <code>filterByExpr()</code> removes genes with too few reads, then the data are normalised, dispersions are estimated, and <code>glmQLFit()</code> and <code>glmQLFTest()</code> do the testing. <code>glmQLFit()</code> is called with <code>legacy = FALSE</code>, the quasi-likelihood method that is the default from edgeR 4.2 onwards; the edgeR in this container is older, so the argument is set explicitly. <code>glmQLFit()</code> fits its coefficients through <code>glmFit()</code>, which adds a small prior count of 0.125 to each count (scaled to library size) before fitting, so the <code>logFC</code> column is lightly shrunk. <code>predFC()</code> computes the same kind of estimate directly.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">design <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model.matrix</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group))</span>
<span id="cb5-2">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y_all, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group)</span>
<span id="cb5-3">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y_all[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb5-4">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateDisp</span>(y, design)</span>
<span id="cb5-5">fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb5-6">qlf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(fit, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb5-7"></span>
<span id="cb5-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># predFC on every gene (no filtering), to see the whole expression range</span></span>
<span id="cb5-9">y_pf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateDisp</span>(y_all, design)</span>
<span id="cb5-10">lfc_predfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predFC</span>(y_pf, design)[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb5-11">predfc_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>predFC.DGEList)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prior.count</span>
<span id="cb5-12">glmfit_default <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(edgeR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span>glmFit.DGEList)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prior.count</span>
<span id="cb5-13">ql_vs_predfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(qlf<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>logFC <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predFC</span>(y, design)[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]))</span>
<span id="cb5-14">kept_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(keep, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu, brk, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> bin_lab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">include.lowest =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>), mean)</span></code></pre></div></div>
</div>
<p>The check agrees: the default prior count is 0.125 in <code>predFC()</code> and 0.125 in <code>glmFit()</code>, and on the filtered genes the <code>glmQLFTest()</code> fold changes and <code>predFC()</code> differ by at most 0.0022. The filtering step matters here too. In this data set <code>filterByExpr()</code> keeps 0% of the genes with a mean count below 2, 0% of those between 2 and 5 and 21% of those between 5 and 10. So edgeR’s standard pipeline never reports a fold change for most of the genes where the pseudocount problem lives. To look at the whole range anyway, the comparison uses <code>predFC()</code> on all genes.</p>
</section>
<section id="what-happens-by-expression-level" class="level2">
<h2 class="anchored" data-anchor-id="what-happens-by-expression-level">What happens by expression level</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">est <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc,</span>
<span id="cb6-2">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bin =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu, brk, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> bin_lab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">include.lowest =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb6-3">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plus1 =</span> lfc_plus1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">logcpm =</span> lfc_logcpm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">predfc =</span> lfc_predfc,</span>
<span id="cb6-4">                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mle =</span> res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">apeglm =</span> shr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange)</span>
<span id="cb6-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># genes with no reads in any sample carry no information; DESeq2 gives them no LFC</span></span>
<span id="cb6-6">all_zero <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(sim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb6-7">n_all_zero <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(all_zero); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mle) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> all_zero))</span>
<span id="cb6-8">est <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> est[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>all_zero, ]</span>
<span id="cb6-9">methods <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plus1 =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log2(count + 1)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">logcpm =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR logCPM"</span>,</span>
<span id="cb6-10">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">predfc =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edgeR predFC"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mle =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2 MLE"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">apeglm =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DESeq2 apeglm"</span>)</span>
<span id="cb6-11">de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> est[est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, ]</span>
<span id="cb6-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># median estimate for genes whose true LFC is +2 or -2 (sign flipped so truth is +2)</span></span>
<span id="cb6-13">med <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(methods), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(de[[m]] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sign</span>(de<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc), de<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin, median))</span>
<span id="cb6-14">rmse <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(methods), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m)</span>
<span id="cb6-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>((est[[m]] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(v) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(v))))</span>
<span id="cb6-16">n_bin_de <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(de<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin)</span>
<span id="cb6-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopifnot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all.equal</span>(headline, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(med[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2-5"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"plus1"</span>]))))</span>
<span id="cb6-18"></span>
<span id="cb6-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a pseudocount added to the group MEAN instead of to each sample before the log</span></span>
<span id="cb6-20">nc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> norm_counts[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>all_zero, ]</span>
<span id="cb6-21">group_mean_lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(c) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(nc[, B]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(nc[, A]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c)</span>
<span id="cb6-22">is_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0.5-2"</span></span>
<span id="cb6-23">gm_low <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.125</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(c)</span>
<span id="cb6-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>((<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_mean_lfc</span>(c) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sign</span>(est<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc))[is_low]))</span></code></pre></div></div>
</div>
<p>Genes with no reads in any sample (14 of them) are dropped, since DESeq2 reports no fold change for them and no method can say anything about them. For the truly changed genes, the sign of the down-regulated ones is flipped so that the right answer is always 2, and each bin gets the median estimate. The bin with the fewest changed genes still holds 109 changed genes.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">plot_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bin =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(bin_lab, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(methods)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> bin_lab),</span>
<span id="cb7-2">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(methods, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(bin_lab)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> methods),</span>
<span id="cb7-3">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">median =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(med))</span>
<span id="cb7-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(plot_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(bin, median, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> method)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> true_abs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#eb9fd2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey45"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#a896e6"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean count of the gene"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Median estimated log2 fold change"</span>,</span>
<span id="cb7-9">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.3</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">guides</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">guide_legend</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-bins" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with mean-count bins on the x axis and median estimated log2 fold change on the y axis. The DESeq2 maximum likelihood and edgeR predFC lines stay near the dashed line at 2 in every bin. The log2 count plus 1 and edgeR logCPM lines start far below 2 in the lowest bin and climb towards 2 as counts rise. The DESeq2 apeglm line starts lowest of all and also climbs towards 2.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-bins-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudocount-log-fold-change/index_files/figure-html/fig-bins-1.png" class="img-fluid figure-img" alt="Line chart with mean-count bins on the x axis and median estimated log2 fold change on the y axis. The DESeq2 maximum likelihood and edgeR predFC lines stay near the dashed line at 2 in every bin. The log2 count plus 1 and edgeR logCPM lines start far below 2 in the lowest bin and climb towards 2 as counts rise. The DESeq2 apeglm line starts lowest of all and also climbs towards 2." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-bins-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Median estimated log2 fold change of genes whose true log2 fold change is 2 (dashed line), by the mean count of the gene. The same simulated data set, five ways of computing the fold change.
</figcaption>
</figure>
</div>
</div>
</div>
<p>DESeq2’s MLE and edgeR’s <code>predFC()</code> stay near the truth in every bin: 1.86 and 1.87 in the lowest bin, where genes have fewer than 2 reads on average. The shortcut does not. With <code>log2(count + 1)</code> the median is 0.81 in that bin, 1.44 between 2 and 5 reads and 1.76 between 5 and 10, and it only reaches 1.91 for genes with 10 to 30 reads. The edgeR log-CPM version, with its larger constant, is lower at every low-count bin: 0.52, 1.09 and 1.51 in the first three. Above 100 reads the methods agree (2.01 to 2.03).</p>
<p>The same true fold change is therefore reported as small or large depending on how many reads the gene has. A lowly expressed transcription factor and a highly expressed structural gene that both quadruple will not look alike in the table.</p>
<p>edgeR’s estimate is not free of a pseudocount either. It adds one, but a small one (0.125), and the log is taken of a fitted group mean rather than averaged over individual samples. You can mimic that without a model: taking <code>log2(group mean + c)</code> on the normalised counts gives a median of 1.83 in the lowest bin with c = 0.125, but 0.87 with c = 1. So what matters is the size of the constant next to the counts, not whether a pseudocount is used at all.</p>
</section>
<section id="the-constant-decides-the-answer" class="level2">
<h2 class="anchored" data-anchor-id="the-constant-decides-the-answer">The constant decides the answer</h2>
<p>The size of the attenuation is set by the constant and the count level, not by the number of samples. This can be computed exactly, without simulation. With unlimited replicates, the average of <code>log2(count + c)</code> in each group converges to its expected value under the negative binomial distribution (for samples of equal depth), and that expectation is a sum over all possible counts.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Expected value of log2(X + c) for a negative binomial X, summed over its distribution</span></span>
<span id="cb8-2">elog <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m, c, disp) {</span>
<span id="cb8-3">  x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qnbinom</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> disp)</span>
<span id="cb8-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dnbinom</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> disp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> c))</span>
<span id="cb8-5">}</span>
<span id="cb8-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what mean(log2(B + c)) - mean(log2(A + c)) converges to with unlimited replicates</span></span>
<span id="cb8-7">expected_lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(mu, c, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_lfc =</span> true_abs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> disp_sim) {</span>
<span id="cb8-8">  muA <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mu <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>true_lfc); muB <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> muA <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span>true_lfc</span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">elog</span>(muB, c, disp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">elog</span>(muA, c, disp)</span>
<span id="cb8-10">}</span>
<span id="cb8-11">mu_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span>))</span>
<span id="cb8-12">c_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb8-13">exact <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand.grid</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> mu_grid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c =</span> c_values)</span>
<span id="cb8-14">exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mapply</span>(expected_lfc, exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu, exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c)</span>
<span id="cb8-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the mean count at which the expected estimate comes within 0.1 of the truth</span></span>
<span id="cb8-16">tol <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span></span>
<span id="cb8-17">mu_within <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(c, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_lfc =</span> true_abs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> disp_sim)</span>
<span id="cb8-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uniroot</span>(<span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expected_lfc</span>(m, c, true_lfc, disp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (true_lfc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> tol), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e4</span>))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>root</span>
<span id="cb8-19">mu_ok_plus1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mu_within</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb8-20">mu_ok_plus5 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mu_within</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb8-21">lfc_big <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb8-22">mu_ok_big <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mu_within</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">true_lfc =</span> lfc_big)           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a larger true change</span></span>
<span id="cb8-23">max_c01 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc[exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>])</span>
<span id="cb8-24">mu_max_c01 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu[exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>][<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which.max</span>(exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc[exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>])]</span>
<span id="cb8-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># more biological variation: same gene (mean 3 reads, c = 1), higher dispersion</span></span>
<span id="cb8-26">disp_hi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>; mu_ex <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb8-27">att_base <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expected_lfc</span>(mu_ex, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb8-28">att_hi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expected_lfc</span>(mu_ex, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> disp_hi)</span>
<span id="cb8-29">mu_ok_disp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mu_within</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">disp =</span> disp_hi)</span>
<span id="cb8-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the exact value for the simulated changed genes in the two lowest bins (median per bin)</span></span>
<span id="cb8-31">exact_bin <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0.5-2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2-5"</span>), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(b)</span>
<span id="cb8-32">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(de<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu[de<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> b], expected_lfc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">c =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)))</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c_lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c ="</span>, exact<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>c), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c ="</span>, c_values))</span>
<span id="cb9-2">x_breaks <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)</span>
<span id="cb9-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(exact, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(mu, lfc, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> c_lab)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> true_abs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_log10</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> x_breaks, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(x_breaks)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#c9bdf0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#9582de"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#3a2687"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1c1147"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean count of the gene (log scale)"</span>,</span>
<span id="cb9-9">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expected log2(x + c) fold change"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-10">  theme_pc</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-exact" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart with mean count on a logarithmic x axis and the expected log2 fold change on the y axis, one line per pseudocount. The line for the smallest pseudocount starts below 2, overshoots well above 2 at a mean of a few reads and then settles on 2. The lines for the larger pseudocounts all start well below 2 at low counts and approach 2 as the count grows, the larger the pseudocount the more slowly.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-exact-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudocount-log-fold-change/index_files/figure-html/fig-exact-1.png" class="img-fluid figure-img" alt="Line chart with mean count on a logarithmic x axis and the expected log2 fold change on the y axis, one line per pseudocount. The line for the smallest pseudocount starts below 2, overshoots well above 2 at a mean of a few reads and then settles on 2. The lines for the larger pseudocounts all start well below 2 at low counts and approach 2 as the count grows, the larger the pseudocount the more slowly." width="672">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-exact-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: What the pseudocount estimator converges to with unlimited replicates, for a gene with a true log2 fold change of 2 (dashed line), as a function of its mean count and of the pseudocount c.&nbsp;Computed exactly from the negative binomial distribution, no simulation.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With c = 1, the expected estimate comes within 0.1 of the true value only once the gene averages about 16 reads. With c = 5 that point moves out to about 128 reads. A small constant fails in the other direction: with c = 0.1 a zero becomes <code>log2(0.1)</code>, about -3.3, so a group with a few zeros is pushed far down, and the expected estimate overshoots to 2.57 for genes averaging about 2.8 reads. Between those choices you can get almost any answer for a low-count gene.</p>
<p>These are two different failures. A constant that is large next to the counts attenuates the fold change. A tiny constant added to each sample before averaging the logs turns every zero into a large negative number and inflates it. Adding the constant to a group mean, as edgeR does in effect, avoids most of the second problem: a single zero no longer drags the group down, and only a group with no reads in any of its samples still does.</p>
<p>More biological variation makes it worse. For a gene averaging 3 reads with c = 1, the expected estimate is 1.42 at the simulated dispersion of 0.1 and 1.29 at a dispersion of 0.5.</p>
<p>Because the mean count is expression multiplied by sequencing depth, the same gene in the same biology also gets a different fold change from <code>log2(count + 1)</code> when it is sequenced deeper. Nothing about the gene has changed; only the constant has become smaller relative to its counts.</p>
</section>
<section id="is-shrinkage-itself-the-problem" class="level2">
<h2 class="anchored" data-anchor-id="is-shrinkage-itself-the-problem">Is shrinkage itself the problem?</h2>
<p>Look again at the first figure. DESeq2’s <code>apeglm</code> estimate is pulled towards zero even harder than the shortcut: 0.19 in the lowest bin and 0.60 between 2 and 5 reads. So a fair question is whether shrinking low-count fold changes is bad at all.</p>
<p>It is not bad in itself. With a handful of reads and 3 samples per group, the MLE is noisy, and pulling noisy estimates towards zero reduces the typical error. Measured as root mean squared error over all genes in the lowest bin (changed and unchanged together), the MLE is off by 1.30, <code>log2(count + 1)</code> by 0.87 and <code>apeglm</code> by 0.95. In that bin the shortcut is actually the most accurate of the three on this measure. Above 100 reads the order changes and <code>apeglm</code> has the smallest error (0.36, against 0.40 for the MLE).</p>
<p>The difference is where the shrinkage comes from. <code>apeglm</code> places a heavy-tailed prior on the fold changes, estimated from all genes, and combines it with each gene’s likelihood (Zhu et al.&nbsp;2019). When a gene carries more information, the likelihood dominates and the shrinkage fades. The pseudocount has no such link to information: its pull depends only on the count level and the constant. Adding replicates separates the two.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">n_rep_big <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260826</span>)</span>
<span id="cb10-3">sim10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulate_counts</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> n_rep_big)</span>
<span id="cb10-4">dds10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeqDataSetFromMatrix</span>(sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group),</span>
<span id="cb10-5">                                      <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> group), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb10-6">res10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds10, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_B_vs_A"</span>)</span>
<span id="cb10-7">shr10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lfcShrink</span>(dds10, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group_B_vs_A"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apeglm"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb10-8">nc10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">counts</span>(dds10, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">normalized =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb10-9">A10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>; B10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>group <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span></span>
<span id="cb10-10">all_zero10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb10-11">est10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lfc =</span> sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc,</span>
<span id="cb10-12">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bin =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(sim10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mu, brk, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> bin_lab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">include.lowest =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb10-13">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plus1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(nc10[, B10] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowMeans</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log2</span>(nc10[, A10] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),</span>
<span id="cb10-14">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mle =</span> res10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">apeglm =</span> shr10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>log2FoldChange)</span>
<span id="cb10-15">est10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> est10[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>all_zero10, ]</span>
<span id="cb10-16">de10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> est10[est10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, ]</span>
<span id="cb10-17">med10 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"plus1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mle"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apeglm"</span>),</span>
<span id="cb10-18">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tapply</span>(de10[[m]] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sign</span>(de10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lfc), de10<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bin, median))</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">m3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"plus1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mle"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apeglm"</span>)</span>
<span id="cb11-2">n_lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(n_rep, n_rep_big), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"per group"</span>)</span>
<span id="cb11-3">rep_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb11-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">bin =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(bin_lab, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> bin_lab),</span>
<span id="cb11-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(methods[m3], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(bin_lab)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> methods[m3]),</span>
<span id="cb11-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(n_lab, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(bin_lab)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> n_lab),</span>
<span id="cb11-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">median =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(med[, m3]), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(med10)))</span>
<span id="cb11-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(rep_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(bin, median, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> n, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> n)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> true_abs, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey40"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> method) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d14fa6"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5a3fc0"</span>), n_lab)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean count of the gene"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Median estimated log2 fold change"</span>,</span>
<span id="cb11-14">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.3</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> theme_pc <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-replicates" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three panels, one per method, each with mean-count bins on the x axis and two lines, one for 3 and one for 10 samples per group. For log2 count plus 1 the two lines lie on top of each other, well below 2 in the low-count bins. For the DESeq2 maximum likelihood estimate both lines stay near 2. For DESeq2 apeglm the 10-sample line sits much closer to 2 than the 3-sample line in the low-count bins.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-replicates-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://pseudocount.com/posts/pseudocount-log-fold-change/index_files/figure-html/fig-replicates-1.png" class="img-fluid figure-img" alt="Three panels, one per method, each with mean-count bins on the x axis and two lines, one for 3 and one for 10 samples per group. For log2 count plus 1 the two lines lie on top of each other, well below 2 in the low-count bins. For the DESeq2 maximum likelihood estimate both lines stay near 2. For DESeq2 apeglm the 10-sample line sits much closer to 2 than the 3-sample line in the low-count bins." width="768">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-replicates-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Median estimated log2 fold change of truly changed genes (true value 2, dashed line) with 3 and with 10 samples per group, for the pseudocount shortcut and the two DESeq2 estimates.
</figcaption>
</figure>
</div>
</div>
</div>
<p>With 10 samples per group instead of 3, the <code>apeglm</code> median in the lowest bin rises from 0.19 to 1.27, and between 2 and 5 reads from 0.60 to 1.73. The MLE stays near the truth in both (1.94 in the lowest bin with 10 samples). The pseudocount shortcut does not move: 0.81 becomes 0.79 and 1.44 becomes 1.44. That is the signature of a bias rather than of noise control. More data makes the estimate more precise, but precise about the wrong number: the exact expected value from the previous section, taken as the median over the changed genes of the first data set, is 0.79 for the lowest bin and 1.44 for the next one.</p>
</section>
<section id="what-to-do-in-practice" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do-in-practice">What to do in practice</h2>
<p>For reporting an effect size, in a results table, a volcano plot or a sentence such as “gene X is up four-fold”, take the fold change from the count model, not from averaged log values. In DESeq2 that is the <code>log2FoldChange</code> from <code>results()</code>, reported with <code>lfcSE</code> (its standard error) or a confidence interval, because at a few reads per sample it is close to unbiased but very noisy. The alternative is the <code>lfcShrink()</code> value, which the DESeq2 vignette describes as useful for visualisation and ranking. Say which one you report, because for low-count genes with few replicates they differ a lot. In edgeR it is the <code>logFC</code> column from <code>glmQLFTest()</code> after <code>filterByExpr()</code>, which simply does not report the genes with the fewest reads.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">normtransform_pc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formals</span>(DESeq2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>normTransform)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pc</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DESeq2: model-based fold changes</span></span>
<span id="cb13-2">dds <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DESeq</span>(dds)</span>
<span id="cb13-3">res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">results</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condition_treated_vs_untreated"</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># MLE, with lfcSE</span></span>
<span id="cb13-4">res_shr <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lfcShrink</span>(dds, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condition_treated_vs_untreated"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apeglm"</span>)</span>
<span id="cb13-5"></span>
<span id="cb13-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edgeR: quasi-likelihood pipeline</span></span>
<span id="cb13-7">keep <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filterByExpr</span>(y, design)</span>
<span id="cb13-8">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">normLibSizes</span>(y[keep, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keep.lib.sizes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>])</span>
<span id="cb13-9">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimateDisp</span>(y, design)</span>
<span id="cb13-10">qlf <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFTest</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmQLFit</span>(y, design, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legacy =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coef =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb13-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">topTags</span>(qlf)                                                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># logFC column</span></span></code></pre></div></div>
</div>
<p>A pseudocount is fine where no effect size is being read off. Heatmaps, PCA, clustering and sample-to-sample distances need values on a log-like scale without minus infinity, and there <code>log2(count + 1)</code> does its job. DESeq2 itself provides <code>normTransform()</code>, which adds 1 by default, and the edgeR help page for <code>cpm()</code> describes CPM values as descriptive measures of expression level. For those tasks DESeq2’s <code>vst()</code> and <code>rlog()</code> are usually better still, since they also deal with the high variance of log counts at low expression, as the vignette explains.</p>
<p>If all you have is a table of <code>log2(x + 1)</code> values, for example from a collaborator or a public supplement, treat fold changes of weakly expressed genes as underestimates of unknown size, and do not compare fold changes between genes with very different expression. How weak is weak depends on the gene. In this simulation the estimate comes within 0.1 of the truth only above about 16 reads, and that is the lower end: for a true log2 fold change of 4 the threshold is about 66 reads, and at a dispersion of 0.5 it is about 28. Also check the units of the table. What matters is the value in the table’s own units next to the constant, so for <code>log2(TPM + 1)</code> or <code>log2(CPM + 1)</code> a value of a few TPM or CPM is the danger zone whatever the read count, and sequencing deeper does not help there. If the constant was much smaller than 1 (0.1 in the second figure), the error can go the other way.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>Love MI, Huber W, Anders S 2014 Genome Biology 15(12):550 (<a href="https://doi.org/10.1186/s13059-014-0550-8">doi:10.1186/s13059-014-0550-8</a>)</li>
<li>Zhu A, Ibrahim JG, Love MI 2019 Bioinformatics 35(12):2084-2092 (<a href="https://doi.org/10.1093/bioinformatics/bty895">doi:10.1093/bioinformatics/bty895</a>)</li>
<li>Chen Y, Lun ATL, Smyth GK 2016 F1000Research 5:1438 (<a href="https://doi.org/10.12688/f1000research.8987.2">doi:10.12688/f1000research.8987.2</a>)</li>
<li>DESeq2 vignette, <a href="https://bioconductor.org/packages/release/bioc/vignettes/DESeq2/inst/doc/DESeq2.html">Analyzing RNA-seq data with DESeq2</a></li>
</ul>
<div class="callout callout-style-default callout-note callout-titled" title="Package versions">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Package versions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The numbers on this page were computed with the versions below.</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>R version 4.5.3 (2026-03-11)
Bioconductor 3.22
apeglm 1.32.0, Biobase 2.70.0, BiocGenerics 0.56.0, DESeq2 1.50.2,
edgeR 4.8.2, generics 0.1.4, GenomicRanges 1.62.1, ggplot2 4.0.3,
IRanges 2.44.0, limma 3.66.0, MatrixGenerics 1.22.0, matrixStats 1.5.0,
S4Vectors 0.48.1, Seqinfo 1.0.0, SummarizedExperiment 1.40.0</code></pre>
</div>
</div>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>RNA-seq</category>
  <category>DESeq2</category>
  <category>edgeR</category>
  <category>fold change</category>
  <category>transformation</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/pseudocount-log-fold-change/</guid>
  <pubDate>Mon, 24 Aug 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/pseudocount-log-fold-change/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
<item>
  <title>Welcome to Pseudocount</title>
  <dc:creator>Pseudocount </dc:creator>
  <link>https://pseudocount.com/posts/welcome/</link>
  <description><![CDATA[ 





<p>Pseudocount is about the statistics inside bioinformatics workflows. A typical tutorial shows a pipeline running from raw counts to a list of genes; the posts here stop at one step of that pipeline and ask what it does to the answer.</p>
<section id="the-format" class="level2">
<h2 class="anchored" data-anchor-id="the-format">The format</h2>
<p>Each post picks a single decision: a normalisation method, a design formula, whether cells or samples are the unit of replication, how a batch is handled, which multiple-testing correction is used. It then simulates data where the truth is known, runs the analysis with and without the problem, and measures the difference. Code comes in R, with Python where that is where the reader is likely to be working.</p>
</section>
<section id="why-simulation" class="level2">
<h2 class="anchored" data-anchor-id="why-simulation">Why simulation</h2>
<p>With real data you rarely know which genes truly changed, so you cannot tell whether a method got it right. With simulated data you can, which turns a debate about methods into a measurement. The cost is that a simulation is only as realistic as its assumptions, and each post says which assumptions it makes.</p>
</section>
<section id="where-to-start" class="level2">
<h2 class="anchored" data-anchor-id="where-to-start">Where to start</h2>
<p>New posts appear on the <a href="https://pseudocount.com/">front page</a>. The <a href="https://pseudocount.com/about/">about page</a> explains how corrections are handled.</p>


</section>

 ]]></description>
  <category>meta</category>
  <guid isPermaLink="false">https://pseudocount.com/posts/welcome/</guid>
  <pubDate>Sun, 23 Aug 2026 21:00:00 GMT</pubDate>
  <media:content url="https://pseudocount.com/posts/welcome/thumbnail.png" medium="image" type="image/png" height="104" width="144"/>
</item>
</channel>
</rss>
